二維陣列

極為常見

二維陣列的使用時機

當你想要將班上的座位表紀錄下來,你會怎麼做? 你可能會拿出一張紙,然後畫出一個 5 橫列 × 7 直行的方格。

alt text

然後將班上座號 1 ~ 35 號的號碼填入表格中,像是這樣:

alt text

然而這件事你想要用程式做到,你可能會先這樣做。

int row1[7] = {1, 2, 3, 4, 5, 6, 7};
int row2[7] = {8, 9, 10, 11, 12, 13,1 4};
int row3[7] = {15, 16, 17, 18, 19, 20, 21};
int row4[7] = {22, 23, 24, 25, 26, 27, 28};
int row5[7] = {29, 30, 31, 32, 33, 34, 35};

但是如果這個座位表有 1000 × 1000 的大小呢?

相信你要照上面的方法顯然就要開非常多條陣列,而且會非常費力對吧?

這時候就是二維陣列出場的時候到了!

基本概念

在前面的章節我們有提到過陣列可以儲存任何型態的資料,而二維陣列就是在陣列的每一項裡面在存一個陣列,也就是說,二維陣列是由多個一維陣列所組成的。

當你把一維陣列想像成一個盒子的時候,二維陣列就是一個盒子裡面還有很多盒子的概念。

第一次聽說這個概念的話,可能會有點難以理解,不過相信我,只要你多練習幾次,你就會發現這個概念其實很簡單。

二維陣列的宣告

想要宣告一個二維陣列,我們會這樣寫。

int seat[5][7];

其中的 5 代表有 5 個橫列 (row), 7 代表有 7 個直行 (col)。

看起來會像這個樣子:

alt text

就像一維陣列一樣,我們可以透過這樣的語法來給予二維陣列初始值:

int seat[5][7] = {
  {1,  2,  3,  4,  5,  6,  7},
  {8,  9,  10, 11, 12, 13, 14},
  {15, 16, 17, 18, 19, 20, 21},
  {22, 23, 24, 25, 26, 27, 28},
  {29, 30, 31, 32, 33, 34, 35}
};

要注意的是,因為二維陣列是多個一維陣列所組成的,所以在宣告的時候要使用兩層的大括號,像是上面所述,最外層的大括號表示整個二維陣列的樣子,內層的括號是組成二維陣列的一維陣列。

通常,我們不管在宣告一維陣列或是二維陣列的時候,我們通常會將宣告出來的陣列歸零,歸零的方法很簡單,就跟一維陣列相同的寫法就好了:

int seat[5][7] = {};
補充

這邊再次強調一下,main 函式外宣告的陣列初始值會是 0,但是在 main 函式內宣告的陣列初始值是隨機的,所以在 main 函式內宣告的陣列最好還是要在存取之前先歸零或是給予初始值。

存取 / 修改二維陣列

存取二維陣列的方式也很簡單,只要透過兩個中括號就可以了。第一個表示橫列 (row),第二個表示直行 (col)。

int seat[5][7] = {
  {1,  2,  3,  4,  5,  6,  7},
  {8,  9,  10, 11, 12, 13, 14},
  {15, 16, 17, 18, 19, 20, 21},
  {22, 23, 24, 25, 26, 27, 28},
  {29, 30, 31, 32, 33, 34, 35}
};

cout << seat[0][0] << endl; // 1
cout << seat[1][3] << endl; // 11
cout << seat[4][6] << endl; // 35

seat[0][0] = 100;

cout << seat[0][0] << endl; // 100

二維的 Vector

前面的章節中,我們提過了 vector 的概念,vector 是一個可以動態調整大小的陣列,而 vector 當然也可以用來宣告二維陣列。

具體的寫法如下:

vector<vector<int>> seat(5, vector<int>(7, 0));

或許新手會有點不了解為什麼這樣就可以宣告二維 vector,不過不用擔心,接下來將會更詳細的解釋這段程式碼的意義。

首先,前面我們提到過 vector 宣告時可以透過 vector<int>(陣列大小, 要填入的值) 這樣的語法來宣告已經包含初始值的 vector。

接著,只要讓我們的 vector 裡面每一項都初始化成一個 vector,就可以達到二維陣列的效果了!

二維陣列與迴圈

我們一般在使用二維陣列的時候,通常會使用到巢狀迴圈,巢狀迴圈就是迴圈中包迴圈,舉例來說,我現在需要將班上的座位表輸入進去,我該怎麼做呢?

  int seat[5][7] = {}; // 宣告一個 5 * 7 的陣列當作座位表
  for (int i = 0; i < 5; i++) { // i 代表橫列
    for (int j = 0; j < 7; j++) { // j 代表直行
      cin >> seat[i][j];
    }
  }

小測驗

main 函式中宣告的陣列,若沒有手動初始化,其內容可能是隨機的?