web-dev-qa-db-fra.com

Mapper un tableau 2D dans un tableau 1D

Je veux représenter un tableau 2D avec un tableau 1D. Une fonction passera les deux indicateurs (x, y) et la valeur à stocker. Ces deux indicateurs représentent un seul élément d'un tableau 1D et le définissent en conséquence. Je sais que le tableau 1D doit avoir la taille de arrayWidth × arrayHeight, mais je ne sais pas comment définir chaque élément.

Par exemple, comment distinguer (2,4,3) de (4,2,3)? J'ai essayé de définir le tableau comme x * y, mais 2 * 4 et 4 * 2 auraient pour résultat le même emplacement dans le tableau et j'ai besoin qu'ils soient différents.

78
Blackbinary

Vous devez décider si les éléments du tableau seront stockés dans l'ordre des lignes ou des colonnes, puis soyez cohérents à ce sujet. http://en.wikipedia.org/wiki/Row-major_order

Le langage C utilise l'ordre des lignes pour les tableaux multidimensionnels

Pour simuler ceci avec un tableau à une seule dimension, multipliez l'index de ligne par la largeur et ajoutez ainsi l'index de colonne de la manière suivante:

 int array[width * height];

 int SetElement(int row, int col, int value)
 {
    array[width * row + col] = value;  
 }
140
John Knoeller

La formule typique pour recalculer des index de tableau 2D en index de tableau 1D est la suivante:

index = indexX * arrayWidth + indexY;

Sinon, vous pouvez utiliser

index = indexY * arrayHeight + indexX;

(en supposant que arrayWidth est mesuré le long de l'axe X et que arrayHeight le long de l'axe Y)

Bien sûr, on peut trouver de nombreuses formules différentes qui fournissent des mappages uniques alternatifs, mais normalement, ce n’est pas nécessaire.

Dans les langages C/C++, les tableaux multidimensionnels intégrés sont stockés en mémoire de sorte que le dernier index change le plus rapidement, ce qui signifie que pour un tableau déclaré comme

int xy[10][10];

élément xy[5][3] est immédiatement suivi de xy[5][4] en mémoire. Vous voudrez peut-être également suivre cette convention en choisissant l'une des deux formules ci-dessus en fonction de l'index (X ou Y) que vous considérez comme le "dernier" des deux.

16
AnT

Exemple: nous voulons représenter un tableau 2D de taille SIZE_X et SIZE_Y. Cela signifie que nous aurons MAXY lignes consécutives de taille MAXX. Par conséquent, la fonction set est

void set_array( int x, int y, int val ) { array[ x * SIZE_Y + y ] = val; }

Le get serait:

int get_array( int x, int y ) { return array[ x * SIZE_Y + y ]; }
15
Kornel Kisielewicz

Comme d'autres l'ont dit C cartes dans l'ordre des lignes

   #include <stdio.h>

   int main(int argc, char **argv) {
   int i, j, k;
   int arr[5][3];
   int *arr2 = (int*)arr;

       for (k=0; k<15; k++) {
          arr2[k] = k;
          printf("arr[%d] = %2d\n", k, arr2[k]);
       }

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

Sortie:

arr[0] =  0
arr[1] =  1
arr[2] =  2
arr[3] =  3
arr[4] =  4
arr[5] =  5
arr[6] =  6
arr[7] =  7
arr[8] =  8
arr[9] =  9
arr[10] = 10
arr[11] = 11
arr[12] = 12
arr[13] = 13
arr[14] = 14
arr2[0][0] =  0
arr2[0][1] =  1
arr2[0][2] =  2
arr2[1][0] =  3
arr2[1][1] =  4
arr2[1][2] =  5
arr2[2][0] =  6
arr2[2][1] =  7
arr2[2][2] =  8
arr2[3][0] =  9
arr2[3][1] = 10
arr2[3][2] = 11
arr2[4][0] = 12
arr2[4][1] = 13
arr2[4][2] = 14
6
Sammy

en utilisant la ligne majeure exemple:

A(i,j) = a[i + j*ld]; // where ld is the leading dimension
                      // (commonly same as array dimension in i)

// matrix like notation using preprocessor hack, allows to hide indexing
#define A(i,j) A[(i) + (j)*ld]

double *A = ...;
size_t ld = ...;
A(i,j) = ...;
... = A(j,i);
1
Anycorn

Il est important de stocker les données de manière à pouvoir les récupérer dans les langues utilisées. Le langage C stocke les objets par rangée majeure (toute la première ligne vient en premier, puis toute la deuxième ligne, ...), chaque index allant de 0 à sa dimension 1. Donc, l'ordre du tableau x [2] [3] est x [0] [0], x [0] [1], x [0] [2], x [1] [0], x [1] [ 1], x [1] [2]. Ainsi, en langage C, x [i] [j] est stocké au même endroit qu'une entrée de tableau à 1 dimension x1dim [i * 3 + j]. Si les données sont stockées de cette manière, il est facile de les récupérer en langage C.

Fortran et MATLAB sont différents. Ils stockent dans l'ordre de la colonne principale (toute la première colonne vient en premier, puis toute la deuxième ligne, ...) et chaque index va de 1 à sa dimension. Donc, l'ordre des index est l'inverse de C et tous les indices sont 1 plus grands. Si vous stockez les données dans l'ordre du langage C, FORTRAN peut rechercher X_C_language [i] [j] à l'aide de X_FORTRAN (j + 1, i + 1). Par exemple, X_C_language [1] [2] est égal à X_FORTRAN (3,2). Dans les tableaux à une dimension, cette valeur de données est X1dim_C_language [2 * Cdim2 + 3], ce qui correspond à la même position que X1dim_FORTRAN (2 * Fdim1 + 3 + 1). N'oubliez pas que Cdim2 = Fdim1 car l'ordre des index est inversé.

MATLAB est identique à FORTRAN. Ada est identique à C, sauf que les index commencent normalement à 1. Les langues sont classées dans l'une des commandes C ou FORTRAN. Les index commencent à 0 ou 1 et peuvent être ajustés en conséquence pour obtenir les données stockées.

Désolé si cette explication est déroutante, mais je pense qu’elle est précise et qu’il est important qu’un programmeur le sache.

1
Mark