ispirato dalla descrizione Wikipedia - Following the cycles algoritmo, sono venuto con seguente C attuazione ++:
#include <iostream> // std::cout
#include <iterator> // std::ostream_iterator
#include <algorithm> // std::swap (until C++11)
#include <vector>
template<class RandomIterator>
void transpose(RandomIterator first, RandomIterator last, int m)
{
const int mn1 = (last - first - 1);
const int n = (last - first)/m;
std::vector<bool> visited(last - first);
RandomIterator cycle = first;
while (++cycle != last) {
if (visited[cycle - first])
continue;
int a = cycle - first;
do {
a = a == mn1 ? mn1 : (n * a) % mn1;
std::swap(*(first + a), *cycle);
visited[a] = true;
} while ((first + a) != cycle);
}
}
int main()
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
transpose(a, a + 8, 4);
std::copy(a, a + 8, std::ostream_iterator<int>(std::cout, " "));
}
Il programma rende la matrice trasposizione sul posto del 2 × 4 matrice
0 1 2 3
4 5 6 7
rappresentato in row-major ordering{0, 1, 2, 3, 4, 5, 6, 7}
nella matrice 4 × 2
0 4
1 5
2 6
3 7
rappresentato dall'ordine di riga principale {0, 4, 1, 5, 2, 6, 3, 7}
.
L'argomento m
di transpose
rappresenta il rowsize, il columnize n
è determinato dal rowsize e dalla dimensione della sequenza. L'algoritmo richiede m
× n
bit di memoria ausiliaria per archiviare le informazioni, quali elementi sono stati scambiati. Gli indici della sequenza sono mappati con il seguente schema:
0 → 0
1 → 2
2 → 4
3 → 6
4 → 1
5 → 3
6 → 5
7 → 7
La funzione di mappatura in generale è:
idx → (idx × n) mod (m × n - 1) se idx < (m × n), idx idx → altrimenti
possiamo identificare quattro cicli all'interno di questa sequenza: { 0 }
, { 1, 2, 4 }
, {3, 5, 6}
e { 7 }
. Ogni ciclo può essere trasposto indipendentemente dagli altri cicli. La variabile cycle
inizialmente punta al secondo elemento (il primo non deve essere spostato perché 0 → 0
). Il bit-array visited
contiene gli elementi già trasposti e indica che l'indice 1 (il secondo elemento) deve essere spostato. L'indice 1 viene scambiato con l'indice 2 (funzione di mappatura). Ora l'indice 1 contiene l'elemento di indice 2 e questo elemento viene scambiato con l'elemento di indice 4. Ora l'indice 1 contiene l'elemento di indice 4. L'elemento di indice 4 deve andare all'indice 1, è nel posto giusto, trasporre del ciclo è terminato, tutti gli indici toccati sono stati contrassegnati come visitati. La variabile cycle
viene incrementata fino al primo indice non visitato, che è 3. La procedura continua con questo ciclo fino a quando tutti i cicli sono stati trasposti.
È possibile, ma non banale. Wikipedia ha la risposta, come al solito. http://en.wikipedia.org/wiki/In-place_matrix_transposition – harold
[Qualche tempo fa ho fatto una domanda simile senza conoscere il termine corretto] (http://stackoverflow.com/q/3009379/237483) –
Grazie Harold! Ho intenzione di elaborare un'implementazione e postarla qui. – UmNyobe