An easy way to transpose in place is to rotate each element in place, starting from the back of the matrix. You only need to rotate one element in place, so for example, starting with [0,1,2,3,4,5,6,7,8,9,a,b]
, you get:
0,1,2,3,4,5,6,7,8,9,a,b, // step 0 ,b, // step 1 ,8,9,a,7, // step 2 4,5,6,8,9,a,3, // step 3 ,a, // step 4 ,8,9,6, // step 5 ,4,5,8,9,2, // step 6 ,9, // step 7 ,8,5, // step 8 ,4,8,1, // step 9 ,8, // step 10 ,4, // step 11 0, // step 12
(This simply shows the elements rotated to their final position at each step.)
If you write out how many elements you need to rotate for each element (from the beginning to the front), it forms a good progression. For example ( width= 4
, height= 3
):
1,4,7,1,3,5,1,2,3,1,1,1
Or, a little better in a structured way:
1,4,7, 1,3,5, 1,2,3, 1,1,1
Rotating 1 element is effectively non-ops, but progression leads to a very simple algorithm (in C ++):
void transpose(int *matrix, int width, int height) { int count= width*height; for (int x= 0; x<width; ++x) { int count_adjustment= width - x - 1; for (int y= 0, step= 1; y<height; ++y, step+= count_adjustment) { int last= count - (y+x*height); int first= last - step; std::rotate(matrix + first, matrix + first + 1, matrix + last); } } }