web-dev-qa-db-fra.com

Comment faire pivoter une matrice de 90 degrés sans utiliser d'espace supplémentaire?

Duplicata possible:
Algorithme pour faire pivoter une image de 90 degrés en place? (Pas de mémoire supplémentaire)

En disant 90 degrés, je veux dire si:

A = {1,2,3,
     4,5,6,
     7,8,9}

puis après une rotation de 90 degrés A devient:

A = {7,4,1,
     8,5,2,
     9,6,3}
45
Vaibhav

soit a une indexation basée sur un tableau nxn 0

f = floor(n/2)
c = ceil(n/2)

for x = 0 to f - 1
  for y = 0 to c - 1
    temp = a[x,y]
    a[x,y] = a[y,n-1-x]
    a[y,n-1-x] = a[n-1-x,n-1-y]
    a[n-1-x,n-1-y] = a[n-1-y,x]
    a[n-1-y,x] = temp

Edit Si vous voulez éviter d'utiliser temp, cela fonctionne (il tourne également dans le bon sens) cette fois en python.

def rot2(a):
  n = len(a)
  c = (n+1) / 2
  f = n / 2
  for x in range(c):
    for y in range(f):
      a[x][y] = a[x][y] ^ a[n-1-y][x]
      a[n-1-y][x] = a[x][y] ^ a[n-1-y][x]
      a[x][y] = a[x][y] ^ a[n-1-y][x]

      a[n-1-y][x] = a[n-1-y][x] ^ a[n-1-x][n-1-y]
      a[n-1-x][n-1-y] = a[n-1-y][x] ^ a[n-1-x][n-1-y]
      a[n-1-y][x] = a[n-1-y][x] ^ a[n-1-x][n-1-y]

      a[n-1-x][n-1-y] = a[n-1-x][n-1-y]^a[y][n-1-x]
      a[y][n-1-x] = a[n-1-x][n-1-y]^a[y][n-1-x]
      a[n-1-x][n-1-y] = a[n-1-x][n-1-y]^a[y][n-1-x]

Remarque: cela ne fonctionne que pour les matrices d'entiers.

54
deinst

Transposez et échangez des lignes ou des colonnes (selon que vous souhaitez faire pivoter vers la gauche ou la droite).

e. g.

1) original matrix

1 2 3
4 5 6
7 8 9

2) transpose

1 4 7
2 5 8
3 6 9

3-a) change rows to rotate left

3 6 9
2 5 8
1 4 7

3-b) or change columns to rotate right

7 4 1
8 5 2
9 6 3

Toutes ces opérations peuvent être effectuées sans allouer de mémoire.

104
Narek

L'algorithme consiste à faire tourner chaque "anneau", en travaillant de l'extérieur vers l'intérieur.

AAAAA
ABBBA
ABCBA
ABBBA
AAAAA

L'algorithme ferait d'abord tourner tous les A, puis les B puis les C. La rotation d'un anneau nécessite le déplacement de 4 valeurs à la fois.

L'indice i varie de 0..ring-width-1, par ex. pour A, la largeur est de 5.

  (i,0) -> temp
  (0, N-i-1) -> (i, 0)
  (N-i-1, N-1) -> (0, N-i-1)
  (N-1, i) -> (N-i-1, N-1)
  temp -> (N-1, i)  

Ceci est ensuite répété pour chaque anneau intérieur successif, compensant les coordonnées réduisant la largeur de l'anneau de 2.

[Une autre réponse est apparue avec le code, donc je ne répéterai pas cela.]

11
mdma

Voir cet article pour la transposition de matrice en place; google également pour la "transposition matricielle sur place". Il peut être facilement adapté pour effectuer une rotation de 90 degrés. Pour transposer des matrices carrées, il vous suffit d'échanger b[i][j] avec b[j][i]b[k][l] est a[n*k+l]. Sur les matrices non carrées, c'est beaucoup plus difficile. "Sans espace supplémentaire" est une exigence assez forte, peut-être vouliez-vous dire O(1) espace? (En supposant que les entiers sont de taille fixe). Implémentation en C++: ici .

3
sdcvvc

Implémentation complète en C en utilisant la méthode décrite par @Narek ci-dessus

#include <stdio.h>

int n;
unsigned int arr[100][100];

void rotate() {

    int i,j,temp;

    for(i=0; i<n; i++) {
        for(j=i; j<n; j++) {
            if(i!=j) {
                arr[i][j]^=arr[j][i];
                arr[j][i]^=arr[i][j];
                arr[i][j]^=arr[j][i];
            }
        }
    }


    for(i=0; i<n/2; i++) {
        for(j=0; j<n; j++) {
            arr[j][i]^=arr[j][n-1-i];
            arr[j][n-1-i]^=arr[j][i];
            arr[j][i]^=arr[j][n-1-i];
        }
    }

}

void display(){

    int i,j;

    for(i=0;i<n;i++) {
        for(j=0;j<n;j++) {
            printf("%d",arr[i][j]);}
            printf("%s","\n");
        }
    }

    int main(int argc, char *argv[]){

    int i,j;

    printf("%s","Enter size of matrix:");
    scanf("%d",&n);

    printf("%s","Enter matrix elements\n");

    for(i=0;i<n;i++) {
        for(j=0;j<n;j++) {
            scanf("%d",&arr[i][j]);
        }
    }

    rotate();
    display();

    return 0;
}
3
user720694

Vous avez besoin d'une variable temporaire, alors il suffit de sauter des éléments.

temp = A[0];
A[0] = A[6];
A[6] = A[8];
A[8] = A[2];
A[2] = temp;
temp = A[1];
A[1] = A[3];
A[3] = A[7];
A[7] = A[5];
A[5] = temp;
2
Albin Sunnanbo

Je suis tombé sur l'implémentation suivante:

Pour les matrices carrées:

for n = 0 to N - 2
    for m = n + 1 to N - 1
        swap A(n,m) with A(m,n)

Pour les matrices rectangulaires:

for each length>1 cycle C of the permutation
    pick a starting address s in C
    let D = data at s
    let x = predecessor of s in the cycle
    while x ≠ s
        move data from x to successor of x
        let x = predecessor of x
    move data from D to successor of s

Pour plus d'informations, on peut se référer ici: http://en.wikipedia.org/wiki/In-place_matrix_transposition

0
Vaibhav