2010-01-27 209 views
63

我想用1D陣列表示2D陣列。函數將傳遞兩個標記(x,y)和要存儲的值。這兩個標記將表示一維數組的單個元素,並對其進行相應設置。我知道1D數組需要具有arrayWidth×arrayHeight的大小,但我不知道如何設置每個元素。將2D陣列映射到1D陣列

例如,如何區分(2,4,3)和(4,2,3)?我嘗試將數組設置爲x * y,但2 * 4和4 * 2會導致數組中的相同點,我需要它們不同。

回答

110

您需要確定數組元素是否將存儲在行順序或列順序,然後保持一致。 http://en.wikipedia.org/wiki/Row-major_order

C語言使用行爲了多維數組

要使用的一維陣列模擬這個,可以通過將寬度乘以行索引,並添加從而列索引:

int array[width * height]; 

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

我認爲這個答案更清晰,特別是對於初學者來說,最好不要將函數寫入一行...... !!這是不好的做法無論如何.. :) – Lipis 2010-01-27 23:38:36

+2

這個答案也是有用的,當你有一個編譯器(如嵌入式系統),沒有適當的multidimensio nal array support – 2013-12-06 21:50:37

+0

令人驚訝的是,有多少人可以正確回答相同的問題,但只有其中一人以易於理解的方式表示。 這就像答案一樣簡單。然而,約翰是唯一真正爲其提供良好答案的人。其餘的垃圾只能被那些已經知道答案的人容易理解。感謝約翰,實際上用英語而不是外星人來說。 只是表明一些人在教學方面有多糟糕,以及John Knoeller這樣的老師如何比其他人更有效地簡化和溝通。 – user2948630 2014-02-15 02:03:53

-2

您應該可以通過簡單的指針訪問2d數組。數組[x] [y]將在指針中排列爲p [0x * width + 0y] [0x * width + 1y] ... [0x * width + n-1y] [1x * width + 0y]等

14

示例:我們想要表示SIZE_X和SIZE_Y大小的二維數組。這意味着我們將有MAXY連續的MAXX大小的行。因此,集功能

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

的get是:使用行主要例如

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

你'MAXX'和'MAXY'值是容易混淆的名字命名,是因爲x'的'最大值和'y'分別是'MAXX - 1'和'MAXY - 1'。也許'SIZE_X'和'SIZE_Y'可能會更好? – caf 2010-01-27 23:29:11

+3

[y * maxx + x]是列順序,而不是行順序。這是matlab工作的方式,但不是數組通常在C中工作的方式。 – 2010-01-27 23:33:20

+0

@John有效點,@caf也 – 2010-01-27 23:38:14

1

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); 
12

用於2D陣列的索引的再計算成一維數組索引的典型配方是

index = indexX * arrayWidth + indexY; 

或者您可以使用

index = indexY * arrayHeight + indexX; 

(假設arrayWidth沿X軸測量的,並且沿着Y軸arrayHeight

當然,可以想出的是提供替代的獨特映射許多不同的公式,但通常沒有必要對。

在C/C++語言內置的多維數組存儲在存儲器中,使得最後索引變化最快的,這意味着用於聲明爲

int xy[10][10]; 

元件xy[5][3]在存儲器之後緊接着xy[5][4]陣列。您可能也想遵循該慣例,根據您認爲哪個索引(X或Y)是兩者中的「最後」選擇上述兩個公式中的一個。

1

以能夠以所用語言檢索數據的方式存儲數據很重要。 C語言存儲按行優先順序排列(第一行首先出現,然後全部第二行,...),每個索引從0運行到它的維度1。因此,數組x [2] [3]的階數爲x [0] [0],x [0] [1],x [0] [2],x [1] [0],x [1] [ 1],x [1] [2]。因此在C語言中,x [i] [j]與1維數組條目x1dim [i * 3 + j]存儲在相同的位置。如果以這種方式存儲數據,則很容易用C語言進行檢索。

Fortran和MATLAB是不同的。它們以列主要順序存儲(第一列首先出現,然後是第二列,...),並且每個索引從1到它的維度。因此,指數順序與C相反,所有指數均大於1。如果以C語言順序存儲數據,FORTRAN可以使用X_FORTRAN(j + 1,i + 1)找到X_C_language [i] [j]。例如,X_C_language [1] [2]等於X_FORTRAN(3,2)。在1維數組中,該數據值位於與X1dim_FORTRAN(2 * Fdim1 + 3 + 1)相同位置的X1dim_C_language [2 * Cdim2 + 3]。請記住Cdim2 = Fdim1,因爲索引的順序是相反的。

MATLAB與FORTRAN相同。除了索引通常從1開始,Ada與C相同。任何語言的索引都在C或FORTRAN命令之一中,索引將從0或1開始,並可以相應地進行調整以獲取存儲的數據。

對不起,如果這個解釋令人困惑,但我認爲它是準確和重要的程序員知道。

6

行順序當其他都該C地圖

#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]); 
     } 
     } 
    } 

輸出:

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