多維陣列

Arvin Liu @ C-Sprout 2021

10sec version

  • 開一個空間為10 * 20的二維陣列

 

  • 開一個空間為10 * 20 * 30 的三維陣列

 

  • 用一個三維陣列的值,如讓第0個二維陣列裡的第2個一維陣列裡面的第5個值等於10

 

  • 總之二維陣列就是一維陣列的一維陣列,三維陣列就是一維陣列的二維陣列(?)
int ary[10][20];
int ary[10][20][30];
ary[0][2][5] = 10;

如果覺得OK就去挑戰吧!

二維陣列?

就是陣列的陣列!

credit to leyna & 蔡銘軒 aka 軒爺/軒神 

Problem: 需要100個放學生成績的空間。

 

宣告空間: int scores[100];

使用空間: scores[0] = 80; ...;  scores[99] = 77; 

最後空間可能就會變成 ...

一維陣列的例子?

neoj294 - 我愛零分

一排分數

0 1 2 1 0

字串(一堆字元)

'H' 'e' 'l' 'l' 'o'

怎會用到二維陣列?

格子狀地圖 ((X,Y)放了甚麼)

很多個一維數據

關係圖 (A,B)=1 表示A喜歡B

A<->B, C<->D C->E

X - - -
X - - -
- - X
- - X -
- - - - X

Rethink: Array

我們要將int scores 複製100份(?)

宣告: (((((int scores))))) [100];

 

那如果我們要將int ary[100]複製30份(?)

宣告: (((((int ary[100]))))) [30];

 

所以要開一個int型態的table變數複製30&30份

int table[30][30];

How to 二維陣列?

Usage

ary[0][0] ary[0][1] ary[0][2] ary[0][3] ary[0][4]
ary[1][0] ary[1][1] ary[1][2] ary[1][3] ary[1][4]
ary[2][0] ary[2][1] ary[2][2] ary[2][3] ary[2][4]
ary[3][0] ary[3][1] ary[3][2] ary[3][3] ary[3][4]
ary[4][0] ary[4][1] ary[4][2] ary[4][3] ary[4][4]

int ary[5][5];

宣告

//做出一個5x5的空間

使用

ary[i][j];

//使用第i個陣列裡面的第j個值

ary[0]

ary[1]

ary[2]

ary[3]

ary[4]

Example

? 1 ? ? ?
? ? 2 ? ?
? ? ? 3 ?
? ? ? ? 4
? ? ? ? ?
int ary[5][5];
ary[0][1] = 1;
ary[1][2] = 2;
ary[2][3] = 3;
ary[3][4] = 4;

code

ary的長相

? : 不可預期的數字 (因為沒有初始化QQ)

Recap: 一維陣列的初始化

Initialization - 初始化1

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
int ary[5][5]={0};

全部初始化成0

int ary[5][5]={};

其實可以連0都不要寫。
(但是有些IDE會出錯,ㄨㄚˊ )

code

ary的長相

Initialization - 初始化2

1 2 3 4 5
6 7 8 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
int ary[5][5] = \
{
  1, 2, 3, 4, 
  5, 6, 7, 8
};

code

ary的長相

前八個元素是1~8,
(會自己換行!)

其他都是0

Initialization - 初始化3

1 2 3 0 0
4 5 6 0 0
7 8 9 0 0
0 0 0 0 0
0 0 0 0 0
int ary[5][5] = \
{
  {1, 2, 3}, 
  {4, 5, 6}, 
  {7, 8, 9}
};

code

ary的長相

左上角3x3個元素變成是1~9,
(利用{}指定換行!)

其他都是0

Initialization - 初始化X

1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
int ary[5][5] = \
{
  {1},
  {0, 1},
  {[2] = 1},
};

code

ary的長相

有些神奇的compiler支援直接指定某個位置要甚麼值。

sorry, unimplemented: non-trivial designated initializers not supported

但是很多時候都不支援QQ,你會拿到下面的error。 (但neoj支援)

Recap: 多重迴圈

credit to leyna & 蔡銘軒 aka 軒爺/軒神 

用for+cin指定陣列元素

int ary[10], n=10;
for(int i=0; i<n; i++){
  cin >> ary[i];
}
int ary[10][10], n=10, m=10;
for(int i=0; i<n; i++){
  for(int j=0; j<m; j++){
    cin >> ary[i][j];
  }
}

陣列不可以做的事情:(

不管是不是多維;(

X_X 多個值只能初始化給

int ary[3]={0};
// 做點事情hehe
ary[0] = 1; 
ary[1] = 2;
ary[3] = 3;
for(int x : ary)
  cout << x << " ";
int ary[3]={0};
// 做點事情hehe
ary = {1, 2, 3};
for(int x : ary)
  cout << x << " ";

只能一個一個給,不能直接用{}給。

X_X 陣列不能直接 =,==

#include <cstring>
...
int A[3]={0};
int B[3]={1, 2, 3};
// 做點事情hehe
memcpy(A, B, sizeof(B));
for(int x : A)
  cout << x << " ";
int A[3]={0};
int B[3]={1, 2, 3};
// 做點事情hehe
A = B;
for(int x : A)
  cout << x << " ";

可以用memcpy複製陣列的值 (或就用for),

但是不能直接讓兩個陣列 =

但是要include cstring

(小小補充) for-each

int A[3]={1, 2, 3};
for(int x : A)
  cout << x << " ";
int A[3]={1, 2, 3};
for(int i=0; i<3; i++){
  x = A[i];
  cout << x << " ";
}

左右是等價的code。
用:的方法稱作for-each,在C++11之後可以使用。

(陣列有偷偷存他到底多大,所以foreach知道跑到哪停)

Quick Review

Quick Review

  • 開一個空間為10 * 20的二維陣列

 

  • 開一個空間為10 * 20,初始化為0。

 

  • 用一個二維陣列的值,如讓第0個一維陣列裡的第2個值等於10

 

  • 要開很大的陣列去全域變數開!
    (就是開在include的下面)
int ary[10][20];
int ary[10][20]={0};
ary[0][2] = 10;

Exercise!

踩地雷

踩地雷(?)

Problem Description

0 0 1
1 0 1
1 0 1
1 3 1
1 5 3
1 4 1

?

?

?

?

?

雙層迴圈

How 2 solve the edge?

Problem Description

Edge Problem

0 0 0 0 0
0 0 0 1 0
0 1 0 1 0
0 1 0 1 0
0 0 0 0 0
1 3 1
1 5 3
1 4 1

Solution

#include <iostream>
using namespace std;
int main(){
    int n, m, cnt[102][102]={0};
    // Input
    cin >> n >> m;
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
            cin >> cnt[i][j];

    for(int i=1; i<=n; i++){
        for(int j=1; j<=m; j++){
            // Calculate
            int mine = -cnt[i][j];
            for(int x=i-1; x<=i+1; x++)
                for(int y=j-1; y<=j+1; y++)
                    mine += cnt[x][y];
            cout << mine << " \n"[j==m];
        }
    }
    return 0;
}

多維陣列?

就是陣列的陣列!

那甚麼時候要用多維陣列呢?

影片: (時間, RGBA, X軸, Y軸)

圖片: (RGBA, X軸, Y軸)

3D場景 (X軸, Y軸, Z軸)

怎麼使用多維陣列呢?

開10 * 20 * 30 的三維陣列,給前2x2x2的方塊為1

開10 * 20 的二維陣列,
給前2x2的方塊為1

int ary[10][20]=\
{
  {1, 1},
  {1, 1}
};
int ary[10][20][30]=\
{
  {
    {1, 1},
    {1, 1}
  },{
    {1, 1},
    {1, 1}
  },
};

使用1-2的值

使用1-2-3的值

cout << ary[1][2];
cout << ary[1][2][3];

陣列不可以做的事情:(

[好大][好大]的陣列

#include <iostream>
int main(){
    char T[10][10]={
        "Kon", 
        "Ban",
        "DODODO!"};
    for(int i=0; i<3; i++)
        puts(T[i]);
    return 0;
}
#include <iostream>
int main(){
    char T[10000][10000]={
        "Kon", 
        "Ban",
        "DODODO!"};
    for(int i=0; i<3; i++)
        puts(T[i]);
    return 0;
}

看起來好像沒有差?

Kon 
Ban
DODODO!
Segmentation fault
(記憶體區段錯誤)

[好大][好大]的陣列

#include <iostream>
int main(){
    char T[10000][10000]={
        "Kon", 
        "Ban",
        "DODODO!"};
    for(int i=0; i<3; i++)
        puts(T[i]);
    return 0;
}
#include <iostream>
char T[10000][10000]={
    "Kon", 
    "Ban",
    "DODODO!"};
int main(){
    for(int i=0; i<3; i++)
        puts(T[i]);
    return 0;
}

開在全域一切OK!

Segmentation fault
(記憶體區段錯誤)
Kon 
Ban
DODODO!

開大概10^6的空間就建議往外開,

但是如果開太大(10^10)可能會吃CE QQ

真的真的很大的陣列

#include <iostream>
char T[1000000][1000000]={
    "Kon", 
    "Ban",
    "DODODO!"};
int main(){
    for(int i=0; i<3; i++)
        puts(T[i]);
    return 0;
}
 error: size of array 'T' is too large
 char T[1000000][1000000]={
                        ^

你該想想你到底出了甚麼問題了..

超出陣列範圍?

好像沒你想像中的簡單...

小小的範例

#include <iostream>
using namespace std;

int main(){
    int A[3][3] = \
    {1, 2, 3, 4, 5, 6, 7, 8, 9};
    for(int i: {0, 1, 2}){
        for (int j : {0, 1, 2})
            cout << A[i][j] << " ";
        cout << endl;
    }
    cout << A[0][0] << endl;
    cout << A[1][3] << endl;
    cout << A[3][4] << endl;
    return 0;
}
1 2 3 
4 5 6
7 8 9
1
7
22021

Code

Output

Uncontrollable

Uncontrollable?

超越! 二維陣列

你感覺好像...

ary[0][0] ary[0][1] ary[0][2]
ary[1][0] ary[1][1] ary[1][2]
ary[2][0] ary[2][1] ary[2][2]

你的記憶體是一條的(?)

不是

超越! 二維陣列

所以其實二維陣列...

ary[0][0] ary[0][1] ary[0][2]
ary[1][0] ary[1][1] ary[1][2]
ary[2][0] ary[2][1] ary[2][2]
ary[0][0] ary[0][1] ary[0][2] ary[1][0] ary[1][1] ary[1][2] ary[2][0] ary[2][1] ary[2][2]

就是一維陣列(?)

=ary[0][3]

=ary[0][4]

=ary[0][5]

=ary[0][6]

=ary[0][7]

=ary[0][8]

=ary[1][3]

=ary[1][4]

=ary[1][5]

1 2 3 4 5
6 7 8 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
int ary[5][5] = \
{
  1, 2, 3, 4, 
  5, 6, 7, 8
};

code

ary的長相

前八個元素是1~8,
(會自己換行!)

其他都是0

超越! 二維陣列

所以這樣初始化是合理的!

不能全部都放生嗎Σ( ° △ °)

但多維陣列只能放生第一個大小參數。

int A[][] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
error: declaration of ‘A’ as multidimensional array 
must have bounds for all dimensions except the first

一維陣列可以放生大小參數。

對啊為甚麼呢?

Challenge Problem!

Problem Description

從I進去貼著左牆走走到O為止,把路徑都踩成*後輸出

nd-array

By Arvin Liu

nd-array

  • 671