二維(多維)陣列


一維陣列使用陣列名稱與一個索引值來指定存取陣列元素,二維陣列使用陣列名稱與兩個索引值來指定存取陣列元素,宣告方式與一維陣列類似:

int maze[5][10];

上面這個宣告會配置 5 * 10 = 50 個整數的記憶體空間給陣列來使用,二維陣列使用兩個索引值來指定存取陣列,這兩個索引值都是由 0 開始,下面這個程式簡單的示範二維陣列的存取:

#include <iostream> 
using namespace std; 

int main() { 
    constexpr int ROWS = 5;
    constexpr int COLUMNS = 10;
    int maze[ROWS][COLUMNS]; 

    for(int row = 0; row < ROWS; row++) {
        for(int i = 0; i < COLUMNS; i++) {
            maze[row][i] = (row + 1) * (i+ 1);
        }
    } 

    for(int row = 0; row < ROWS; row++) {
        for(int i = 0; i < COLUMNS; i++) {
            cout << maze[row][i] << "\t"; 
        }
        cout << endl; 
    } 

    return 0; 
}

執行結果:

1       2       3       4       5       6       7       8       9       10      
2       4       6       8       10      12      14      16      18      20      
3       6       9       12      15      18      21      24      27      30
4       8       12      16      20      24      28      32      36      40
5       10      15      20      25      30      35      40      45      50

上面這個程式宣告了 5 列(Row)、10 行(Column)的陣列,第一個 [] 是用來指定存取哪一列,第二個 [] 是用來指定存取哪一行。

可以在宣告二維陣列的同時指定二維陣列的值,例如:

int maze[2][3] = {
                     {1, 2, 3},
                     {4, 5, 6}
                 };

從上面這個程式來看,可以清楚地看出 maze[2][3] 中 2 與 3 的意義,maze[2] 表示 maze 有兩個元素,各是 {1, 2, 3}{4, 5, 6},也就是說,這兩個元素是一維陣列,而長度是 3。

若清楚二維陣列的記憶體配置方式,會理解到 {} 其實是可以不用的,例如:

int maze[2][3] = {
                     1, 2, 3,
                     4, 5, 6
                 };

何謂二維陣列於記憶體中的配置方式?其實二維陣列存取時的行與列,只是為了便於理解陣列元素索引,索引值真正的意義,還是〈一維陣列〉中談到的,是指相對於陣列第一個元素的位移量,例如,在一維陣列中的陣列配置與索引意義如下圖所示(若 int 長度為 4 個位元組):

二維(多維)陣列

int 陣列來說,每次位移量是 4 個位元組,指定存取 maze[4],相當於指定存取相對於 maze[0] 四個位移量的記憶體空間。

二維陣列在記憶體中也是線性配置,例如:

二維(多維)陣列

在上面的例子中,二維陣列將得到的記憶體分為兩個區塊,宣告陣列 maze[2[4],表示 maze[0][0]maze[1][0] 相對位移量為 4,存取 maze[1][3] 時,表示存取位置相對於 maze[1][0] 位移3個單位。

若宣告 maze[3][5] 的話,記憶體位置的指定是如何呢?在這個陣列中 5 的意義是 maze[0][0]maze[1][0]maze[2][0] 間都是 5 個位移量,如下圖所示:

二維(多維)陣列

瞭解二維陣列在記憶體中的配置關係後,就可以知道,上圖可以看成是三個一維陣列在記憶體中連續配置,嚴格來說,C++ 沒有二維陣列這種東西,二維或多維陣列的概念,是以陣列的陣列(arrays of arrays)來實現。

在 C++ 11 新增了 for range 語法,可以使用這個語法來驗證所謂的二維陣列,就是具有兩個一維陣列作為元素的陣列:

#include <iostream> 
using namespace std; 

int main() { 
    int maze[2][3] = {
                         {1, 2, 3},
                         {4, 5, 6}
                     };

    for(auto row : maze) {
        for(int i = 0; i < 3; i++) {
            cout << row[i] << "\t"; 
        }
        cout << endl; 
    } 

    return 0; 
}

row 的型態實際上是 int*,這是指標型態,之後會談到;那麼可不可以用兩個 for range 來執行相同的任務呢?這需要知道參考(reference)是什麼,之後也會談到,就結論而言,可以如下:

#include <iostream> 
using namespace std; 

int main() { 
    int maze[2][3] = {
                         {1, 2, 3},
                         {4, 5, 6}
                     };

    for(auto &row : maze) {
        for(auto n : row) {
            cout << n << "\t"; 
        }
        cout << endl; 
    } 

    return 0; 
}

更多維的陣列,就是依以上說明類推罷了,例如三維陣列:

int arr[2][4][6];