Un manuel que j'ai lu récemment a traité des tableaux de lignes majeures et de colonnes majeures. Le livre portait principalement sur les tableaux à 1 et 2 dimensions, mais ne traitait pas vraiment des tableaux à 3 dimensions. Je suis à la recherche de bons exemples pour renforcer ma compréhension de l'adressage d'un élément dans un tableau multidimensionnel à l'aide de tableaux de lignes et de colonnes.
+ - + - + - + | //// | | + - + - + - + + | + --- + --- + --- + --- + //// |/| |//// /| + - + - + - + + + | + --- + --- + --- + --- + + //// |/|/| |//// /|/| + - + - + - + + + + + | + --- + --- + --- + --- + + + //// |/|/|/| |//// /|/|/| + - + - + - + + + + + + | + --- + --- + --- + --- + + + + + //// |/|/|/| | 000 | 001 | 002 | 003 |/|/|/| + - + - + - + + + + + + | + --- + --- + --- + --- + + + + + | 00 | 01 | 02 |/|/|/|/| | 004 | 005 | 006 | 007 |/|/|/| + - + - + - + + + + + | + --- + --- + --- + --- + + + + + | 03 | 04 | 05 |/|/|/| | 008 | 009 | 00A | 00B |/| Gite | / + - + - + - + + + + | + --- + --- + --- + --- + + + | 06 | 07 | 08 |/|/| | 00C | 00D | 00E | 00F |/| / + - + - + - + + | + --- + --- + --- + --- + + | 09 | 0A | 0B |/| | 010 | 011 | 012 | 013 | / + - + - + - + | + --- + --- + --- + --- + arr [5] [3] [4] | arr [3] [4] [5]
REMARQUE: Question originale mal représentée arr [3] [4] [5]. J'ai appris que l'indice initial représentait la profondeur. Les données ont été corrigées pour refléter la représentation de tableau souhaitée.
Exemple de données hexadécimales + --- + --- + --- + --- + + --- + --- + --- + --- + --- + + - - + --- + --- + --- + | 000 | 001 | 002 | 003 | | 100 | 101 | 102 | 103 | | 200 | 201 | 202 | 203 | + --- + --- + --- + --- + --- + --- + --- + --- + --- --- + --- + - - + --- + | 004 | 005 | 006 | 007 | | 104 | 105 | 106 | 107 | | 204 | 205 | 206 | 207 | + --- + --- + --- + --- + --- + --- + --- + --- + --- --- + --- + - - + --- + | 008 | 009 | 00A | 00B | | 108 | 109 | 10A | 10B | | 208 | 209 | 20A | 20B | + --- + --- + --- + --- + --- + --- + --- + --- + --- --- + --- + - - + --- + | 00C | 00D | 00E | 00F | | 10C | 10D | 10E | 10F | | 20C | 20D | 20E | 20F | + --- + --- + --- + --- + --- + --- + --- + --- + --- + + + - - - + --- + --- + --- + | 010 | 011 | 012 | 013 | | 110 | 111 | 112 | 113 | | 210 | 211 | 212 | 213 | + --- + --- + --- + --- + + --- + --- + --- + --- + --- + + - - - + --- + --- + --- + tranche 0 tranche 1 tranche 2 court Arr [3] [4] [5]; // suppose que le tableau est rempli de données de test hexadécimales arr [1] [2] [3] = 0x10B utilisez la tranche 1, rangée 2, colonne 3 arr [2] [3] [4] = 0x210, utilisez la tranche 2, ligne 3, colonne 4 Correspond à la ligne 4, colonne 0
rangée majeure
[En stock] 20A, 20B, 20C, 20D, 20E, 20F, 210,211,212,213}
major de colonne {000,004,008,00C, 010,001,005,009,00D, 011,002,006,00A, 00E, 012,003,007,00B, 00F, 013, 100,104,108,10C, 110,105,109,109,10D, 111,1010, , 10B, 10F, 113, 200,204,208,20C, 210,201,205,209,20D, 211,202,206,20A, 20E, 212,203,207,20B, 20F, 213}
Décalage de calcul pour arr [1] [2] [3] en utilisant le décalage principal de ligne? Décalage de calcul pour arr [1] [2] [3] en utilisant le décalage principal de colonne?
Lorsque j'ai posé cette question, j'espérais trouver de bons exemples de tableaux en 3 dimensions. Surtout des exemples de code. N'ayant rien trouvé de compréhensible, j'ai décidé de créer un petit programme en C pour aider à afficher le concept. Il utilise les mêmes données de test dans un tableau 3x4x5. Il comprend également des données de test pour un tableau 5x5x5. Il crée un tableau majeur de colonne à partir du tableau principal de ligne afin que les calculs de décalage puissent être vérifiés.
Les méthodes de décalage de tableau sont:
//
// Arrays.cpp :
// Purpose: Display rowMajor & colMajor data and calculations.
//
#include "stdafx.h"
#define _show_Arrays 1 // 1=display rowMajor & colMajor arrays
#define _square_array 0 // 1=use arr[5][5][5], 0=use arr[3][4][5]
#if (_square_array == 1)
const int depthSz = 5;
const int rowSz = 5;
const int colSz = 5;
/*
+---+---+---+---+---+
|x00|x01|x02|x03|x04|
+---+---+---+---+---+
|x05|x06|x07|x08|x09|
+---+---+---+---+---+
|x0A|x0B|x0C|x0D|x0E|
+---+---+---+---+---+
|x0F|x10|x11|x12|x13|
+---+---+---+---+---+
|x14|x15|x16|x17|x18|
+---+---+---+---+---+
slice x
*/
short row_arr[depthSz][colSz][rowSz] = {
{ /* slice 0 */
{0x000,0x001,0x002,0x003,0x004},
{0x005,0x006,0x007,0x008,0x009},
{0x00A,0x00B,0x00C,0x00D,0x00E},
{0x00F,0x010,0x011,0x012,0x013},
{0x014,0x015,0x016,0x017,0x018}},
{ /* slice 1 */
{0x100,0x101,0x102,0x103,0x104},
{0x105,0x106,0x107,0x108,0x109},
{0x10A,0x10B,0x10C,0x10D,0x10E},
{0x10F,0x110,0x111,0x112,0x113},
{0x114,0x115,0x116,0x117,0x118}},
{ /* slice 2 */
{0x200,0x201,0x202,0x203,0x204},
{0x205,0x206,0x207,0x208,0x209},
{0x20A,0x20B,0x20C,0x20D,0x20E},
{0x20F,0x210,0x211,0x212,0x213},
{0x214,0x215,0x216,0x217,0x218}},
{ /* slice 3 */
{0x300,0x301,0x302,0x303,0x304},
{0x305,0x306,0x307,0x308,0x309},
{0x30A,0x30B,0x30C,0x30D,0x30E},
{0x30F,0x310,0x311,0x312,0x313},
{0x314,0x315,0x316,0x317,0x318}},
{ /* slice 4 */
{0x400,0x401,0x402,0x403,0x404},
{0x405,0x406,0x407,0x408,0x409},
{0x40A,0x40B,0x40C,0x40D,0x40E},
{0x40F,0x410,0x411,0x412,0x413},
{0x414,0x415,0x416,0x417,0x418}}
};
#else
const int depthSz = 3;
const int rowSz = 4;
const int colSz = 5;
/*
+---+---+---+---+
|000|001|002|003|
+---+---+---+---+
|004|005|006|007|
+---+---+---+---+
|008|009|00A|00B|
+---+---+---+---+
|00C|00D|00E|00F|
+---+---+---+---+
|010|011|012|013|
+---+---+---+---+
slice x
*/
short row_arr[depthSz][colSz][rowSz] = {
{ /* slice 0 */
{0x000,0x001,0x002,0x003},
{0x004,0x005,0x006,0x007},
{0x008,0x009,0x00A,0x00B},
{0x00C,0x00D,0x00E,0x00F},
{0x010,0x011,0x012,0x013}},
{ /* slice 1 */
{0x100,0x101,0x102,0x103},
{0x104,0x105,0x106,0x107},
{0x108,0x109,0x10A,0x10B},
{0x10C,0x10D,0x10E,0x10F},
{0x110,0x111,0x112,0x113}},
{ /* slice 2 */
{0x200,0x201,0x202,0x203},
{0x204,0x205,0x206,0x207},
{0x208,0x209,0x20A,0x20B},
{0x20C,0x20D,0x20E,0x20F},
{0x210,0x211,0x212,0x213}}
};
#endif
short col_arr[depthSz*colSz*rowSz]; //
char *calc_RowMajor(char *Base, int elemSz, int depth_idx, int row_idx, int col_idx)
{ // row major slice is navigated by rows
char *address;
int lbound = 0; // lower bound (0 for zero-based arrays)
address = Base /* use base passed */
+ ((depth_idx-lbound)*(colSz*rowSz*elemSz)) /* select slice */
+ ((row_idx-lbound)*rowSz*elemSz) /* select row */
+ ((col_idx-lbound)*elemSz); /* select col */
return address;
}
char *calc_ColMajor(char *Base, int elemSz, int depth_idx, int col_idx, int row_idx)
{ // col major slice is navigated by columns
char *address;
int lbound = 0; // lower bound (0 for zero-based arrays)
int pageSz = colSz*rowSz*elemSz;
int offset;
offset = (col_idx-lbound)*(colSz*elemSz) /* select column */
+ (row_idx-lbound)*(elemSz); /* select row */
if (offset >= pageSz)
{ // page overflow, rollover
offset -= (pageSz-elemSz); /* ajdust offset back onto page */
}
address = Base /* use base passed */
+ ((depth_idx-lbound)*pageSz) /* select slice */
+ offset;
return address;
}
void disp_slice(char *pStr, short *pArr,int slice,int cols, int rows)
{
printf("== %s slice %d == %p\r\n",pStr, slice,pArr+(slice*rows*cols));
for(int x=0;x<rows;x++)
{
for(int y=0;y<cols;y++)
printf("%03X ",*(pArr+(slice*rows*cols)+(x*cols)+y));
printf("\r\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
// initialize col based array using row based array data
{ // convert row_arr into col_arr
short *pSrc = &row_arr[0][0][0];
short *pDst = &col_arr[0];
for(int d=0;d<depthSz;d++)
for(int r=0;r<rowSz;r++)
for(int c=0;c<colSz;c++)
{
*pDst++ = *(pSrc+((d*rowSz*colSz)+(c*rowSz)+r));
}
}
printf("Using Array[%d][%d][%d]\r\n",depthSz,rowSz,colSz);
#if (_show_Arrays == 1)
{ for(int x=0;x<depthSz;x++) {disp_slice("rowMajor",&row_arr[0][0][0],x,rowSz,colSz);}}
{ for(int x=0;x<depthSz;x++) {disp_slice("colMajor",&col_arr[0],x,rowSz,colSz);}}
#endif
int d = 2; // depth
int r = 3; // row
int c = 4; // column
for(d=0;d<depthSz;d++)
{
c = r = d; // simple access test pattern arr[0][0][0],arr[1][1][1],arr[2][2][2],...
{ // retrieve Array element
printf(" row_arr[%d][%d][%d] = %x\t",d,r,c,row_arr[d][r][c]);
printf("&row_arr[%d][%d][%d] = %p\r\n",d,r,c,&row_arr[d][r][c]);
}
{ // retrieve RowMajor element
short *pRowMajor = (short*)calc_RowMajor((char*)&row_arr[0][0][0],sizeof(short),d,r,c);
printf("calc_RowMajor(%d,%d,%d) = %x\t\t",d,r,c,*pRowMajor);
printf("pRowMajor = %p\r\n",pRowMajor);
}
{ // retrieve ColMajor element
short *pColMajor = (short*)calc_ColMajor((char*)&col_arr[0],sizeof(short),d,c,r);
printf("calc_ColMajor(%d,%d,%d) = %x\t\t",d,r,c,*pColMajor);
printf("pColMajor = %p\r\n",pColMajor);
}
} // for
getchar(); // just to hold the console while looking at the information
return 0;
}
Ne vous contraignez pas artificiellement en vous concentrant sur 3 dimensions et 2 dimensions. Au lieu de cela concentrez-vous sur l'apprentissage de l'expression permettant d'adresser des tableaux à n dimensions .
Exprimer un adressage n-dimensionnel solidifierait votre compréhension sur ce sujet et serait plus facile de se souvenir d'une formule plutôt que de formules séparées pour l'adressage 2D et 3D.
Voici ma tentative d'adressage n-dimensionnel:
#define LEN 10
int getValue_nDimensions( int * baseAddress, int * indexes, int nDimensions ) {
int i;
int offset = 0;
for( i = 0; i < nDimensions; i++ ) {
offset += pow(LEN,i) * indexes[nDimensions - (i + 1)];
}
return *(baseAddress + offset);
}
int main() {
int i;
int * baseAddress;
int val1;
int val2;
// 1 dimensions
int array1d[LEN];
int array1d_indexes[] = {2};
int array1d_nDimensions = 1;
baseAddress = &array1d[0];
for(i = 0; i < LEN; i++) { baseAddress[i] = i; }
val1 = array1d[2];
val2 = getValue_nDimensions( // Equivalent to: val1 = array1d[2];
baseAddress,
&array1d_indexes[0],
array1d_nDimensions
);
printf("SANITY CHECK: %d %d\n",val1,val2);
// 3 dimensions
int array3d[LEN][LEN][LEN];
int array3d_indexes[] = {2,3,4};
int array3d_nDimensions = 3;
baseAddress = &array3d[0][0][0];
for(i = 0; i < LEN*LEN*LEN; i++) { baseAddress[i] = i; }
val1 = array3d[2][3][4];
val2 = getValue_nDimensions( // Equivalent to: val1 = array3d[2][3][4];
baseAddress,
&array3d_indexes[0],
array3d_nDimensions
);
printf("SANITY CHECK: %d %d\n",val1,val2);
// 5 dimensions
int array5d[LEN][LEN][LEN][LEN][LEN];
int array5d_indexes[] = {2,3,4,5,6};
int array5d_nDimensions = 5;
baseAddress = &array5d[0][0][0][0][0];
for(i = 0; i < LEN*LEN*LEN*LEN*LEN; i++) { baseAddress[i] = i; }
val1 = array5d[2][3][4][5][6];
val2 = getValue_nDimensions( // Equivalent to: val1 = array5d[2][3][4][5][6];
baseAddress,
&array5d_indexes[0],
array5d_nDimensions
);
printf("SANITY CHECK: %d %d\n",val1,val2);
return 0;
}
Sortie:
SANITY CHECK: 2 2
SANITY CHECK: 234 234
SANITY CHECK: 23456 23456
Je verrais le ordre de rangée-majeur article Wikipedia. Il y a une section qui décrit les dimensions supérieures à 2. Il y a aussi un bon article ici . Cet article donne la formule suivante pour un tableau à trois dimensions utilisant une présentation en lignes majeures:
Address = Base + ((depthindex*col_size+colindex) * row_size + rowindex) * Element_Size
Pour un tableau 3D: tapez A [profondeur] [col] [ligne]. La base est le décalage de départ du tableau. De plus, les variables de taille sont les différentes tailles de chaque dimension. La variable Element_Size indique la taille de tout type de composition du tableau.
Supposons que vous ayez un tableau ligne-majeur a [4] [6] [5] composé d'entiers C++ standard. Pour calculer le décalage d'un 1 [3] 2 , vous devez insérer les nombres suivants dans la formule:
Address = Base + ((1 * 6 + 3) * 5 + 2) * 4
Pour un tableau à 3 dimensions ayant une disposition colonne-majeur, l'équation serait plutôt la suivante:
Address = Base + ((rowindex*col_size+colindex) * depth_size + depthindex) * Element_Size
Les numéros que vous utiliseriez pour l'exemple ci-dessus en utilisant une disposition colonne-majeur seraient les suivants:
Address = Base + ((2 * 6 + 3) * 4 + 1) * 4
Les termes "ligne majeure" et "colonne majeure" ne se traduisent pas bien en une troisième dimension. La notion selon laquelle l'élément suivant stocké provient de la ligne ou de la colonne en cours est décomposée. Cela semble un peu comique, mais cela devient un ordre «profondeur majeure» contre un ordre «largeur majeure». Chaque élément suivant n'est plus une entrée unique mais une matrice complète à deux dimensions.
/X / + --- + --- + --- + //// | + --- + --- + --- + - + ------- | 1 | 5 | 9 |/| Y + --- + --- + --- + + | 2 | 6 | A |/| + --- + --- + --- + + | 3 | 7 | B |/| + --- + --- + --- + + | 4 | 8 | C | / + --- + --- + --- +
Ainsi, la mémoire aurait littéralement 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 en mémoire séquentiellement. C’est l’ordre des colonnes classiques. En plaçant l'entrée D à la position marquée X, vous n'avez pas modifié le fait que votre matrice est en ordre de priorité. Si vous placez l'entrée D où le Y est, vous n'avez toujours pas changé le fait que vous utilisez le classement par colonne. L'emplacement où vous décidez de placer le prochain bloc aura une incidence sur le fait que vous utilisiez l'ordre de profondeur majeure (X) ou de largeur majeure (Y). Comme vous le savez bien, ce sont des équivalents, mais appeler quelque chose peut vous aider à écrire des équations:
[0 Bases supposées]
Vous accédez à l'emplacement de la mémoire d'un élément majeur de colonne à deux dimensions via l'équation:
MatrixOffset = base + (sizeof(entry) * ((4 * ( column - 1 )) + (row - 1)))
Cette adresse serait ajustée en fonction de la profondeur ou de la largeur, tout était une question de terminologie.
TotalOffset = MatrixOffset + (sizeof(entry) * ((4 * 3) * (depth - 1)))
OU
TotalOffset = MatrixOffset + (sizeof(entry) * ((4 * 3) * (width - 1)))
Les constantes 4 et 3 seraient probablement les variables COLUMNS et ROWS.
Ne me demandez pas à propos du 4ème dimention!
En gros, dans un tableau 3D avec une rangée majeure, par exemple Arr Arr [3] [4] [5] Lorsque vous voulez Arr [0], la partie avant de l'image est recherchée comme ci-dessus Arr [ 1] deuxième tranche et ainsi de suite. Donc Arr [0] désigne un tableau 2D de taille [4] [5], ainsi chaque Arr [x] correspond à x * (4 * 5) Maintenant, à propos de Arr [x] [y], on peut penser à un tableau 1D de taille [5] dont la position est [x] [y] à partir de la vue de dessus dans l'image ci-dessus Alors quand on veut Arr [x ] [y] = x * (4 * 5) + y * (5) maintenant Arr [x] [y] [z] est l’élément spécifique d’Arr [x] [y] à la profondeur z Arr [x] [y] [z] = x * (4 * 5) + y * 5 + z Maintenant sur la base de la taille du type de données que vous souhaitez stocker dans le tableau , le décalage peut être multiplié par la taille obtenir l'adresse par rapport au début
La formule pour les tableaux de dimension k est
k-1 n
i + ∑ i * ∏ c
0 n=1 n m=0 m
où i indice n est l'indice de la dimension n pour n = {0, 1, 2, ... k-1} et c indice m est la cardinalité de la dimension m pour m = {0, 1, 2, ... k-2}.
Un rendu plus agréable de la formule au format PNG peut être trouvé ici:
http://modula-2.info/m2r10/pmwiki.php/Spec/LanguageReport#MultiDimensionalArrays