### C程式設計導論 ### 陣列 --- <!-- .slide: data-transition="fade" --> <h3 class="text-left"> Table of Contents </h3> - 認識陣列 - 一維陣列 - 奇奇怪怪的一維陣列操作 - 二維陣列 - 奇奇怪怪的二維陣列操作 - 例題練習 ---- <!-- .slide: data-transition="fade" --> ### 為了節省講義空間 ### 從這裡開始會習慣性省略以下幾行程式 ```cpp #include<stdio.h> int main(){ return 0; } ``` <!-- .element: class="fragment" data-fragment-index="1" --> --- ### 認識陣列 ---- <!-- .slide: data-transition="fade" --> **在前面的章節 我們學了如何宣告變數** ```cpp int n, a, b, c; char s1, s2; ``` ---- <!-- .slide: data-transition="fade" --> **這時可以想個問題** **如果需要一次處理數以萬計的資料時** **應該會宣告變數到手軟吧** <!-- .element: class="fragment" data-fragment-index="1" --> **就算可以** **這樣宣告出來的資料也不方便使用** <!-- .element: class="fragment" data-fragment-index="2" --> ---- <!-- .slide: data-transition="fade" --> **因此 我們需要一個東西來滿足以下需求** - **一次宣告多筆資料** - **方便取用** **這個東西就是 陣列** <!-- .element: class="fragment" data-fragment-index="1" --> --- <!-- .slide: data-transition="fade" --> ### 一維陣列 ---- <!-- .slide: data-transition="fade" --> <h3 class="text-left"> 一維陣列的宣告方式 </h3> ```cpp int arr[105]; // 宣告int陣列 大小為105 ``` **這指令告訴電腦你需要105個空間儲存int** <!-- .element: class="fragment" data-fragment-index="1" --> **如此一來他就會分配105個連續空間給你** <!-- .element: class="fragment" data-fragment-index="2" --> ---- <!-- .slide: data-transition="fade" --> **想當然爾 其他資料型態也可以宣告陣列** ```cpp int arr[10]; char str[105]; float f1[10000]; double handsome[55]; ``` ---- <!-- .slide: data-transition="fade" --> **陣列取用是使用編號來存取** **假設我今天宣告了一個大小$100$的陣列** **那我的陣列編號就會是$0$到$99$** <!-- .element: class="fragment" data-fragment-index="1" --> **假設我今天宣告了一個大小$n$的陣列** **那我的陣列編號就會是$0$到$n - 1$** <!-- .element: class="fragment" data-fragment-index="2" --> ---- <!-- .slide: data-transition="fade" --> **陣列可以想像成格子** ![image](https://hackmd.io/_uploads/rkG-w1YcC.png) **編號從$0$開始數算是慣例(我也不知道為什麼)** <!-- .element: class="fragment" data-fragment-index="1" --> ---- <!-- .slide: data-transition="fade" --> **裡面可以儲存數字** ![image](https://hackmd.io/_uploads/Sy4PDJKqA.png) ---- <!-- .slide: data-transition="fade" --> <h3 class="text-left"> 一維陣列存取 </h3> ```cpp int arr[8]; // 宣告大小 8 的int陣列 arr[0] = 10; // arr位置 0 存入 10 arr[5] = 20; // arr位置 0 存入 20 printf("%d %d", arr[0], arr[5]); // 輸出 "10 20" ``` ![image](https://hackmd.io/_uploads/Sy4PDJKqA.png) ---- <!-- .slide: data-transition="fade" --> **編號一般稱為index或是idx** **注意不可以去存取超出範圍的idx** ![image](https://hackmd.io/_uploads/rJVpD1F9C.png) **這樣電腦會報錯** **因為電腦看不懂這是哪裡** <!-- .element: class="fragment" data-fragment-index="1" --> --- <!-- .slide: data-transition="fade" --> ### 奇奇怪怪的一維陣列操作 ---- <!-- .slide: data-transition="fade" --> **操作陣列 我們通常會使用迴圈** ```cpp int arr[10]; // 宣告大小 10 的陣列 for(int i = 0; i < 10; i++){ // i 從 0 到 10 arr[i] = i + 1; // 編號 idx=i 存入 i+1 } for(int i = 0; i < 10; i++){ printf("%d ", arr[i]); // 輸出陣列編號 i 的數值 } ``` ---- <!-- .slide: data-transition="fade" --> **輸入十個數字** ```cpp int arr[10]; // 宣告大小 10 的陣列 for(int i = 0; i < 10; i++){ // i 從 0 到 10 scanf("%d", &arr[i]); // 輸入陣列編號 i 的數值 } for(int i = 0; i < 10; i++){ printf("%d ", arr[i]); // 輸出陣列編號 i 的數值 } ``` ---- <!-- .slide: data-transition="fade" --> **宣告時就塞數字給陣列** ```cpp int arr[8] = {0, 8, 4, 8, 7, 8, 7, 8}; ``` ![image](https://hackmd.io/_uploads/Bk9HK1YqC.png) ---- <!-- .slide: data-transition="fade" --> **取陣列中的最小值** ```cpp int arr[8] = {7, 9, -1, 3, 4, 15, 7, 2}; int mn = 105; // mn 一定要是一個比陣列內的數字還要大的值 for(int i = 0; i < 8; i++){ if(mn > arr[i]){ mn = arr[i]; } } printf("%d", &mn); ``` ---- <!-- .slide: data-transition="fade" --> **反著輸出陣列** ```cpp int arr[8] = {7, 9, -1, 3, 4, 15, 7, 2}, n = 8; for(int i = n - 1; i >= 0; i--){ // 從 n-1 到 0,每次 i 減 1 printf("%d ", arr[i]); } ``` **或是** ```cpp int arr[8] = {7, 9, -1, 3, 4, 15, 7, 2}, n = 8; for(int i = 0; i < n; i++){ printf("%d ", arr[n - i - 1]); // 很trivial的減法操作 } ``` ---- <!-- .slide: data-transition="fade" --> **輸出陣列五次** ```cpp int arr[8] = {7, 9, -1, 3, 4, 15, 7, 2}, n = 8, m = 5; for(int i = 0; i < m; i++){ // 重複 m 次 for(int j = 0; j < n; j++){ // 輸出 arr[i], i = 0 ~ n-1 printf("%d ", arr[j]); } printf("\n"); // 換行 } ``` **或是** ```cpp int arr[8] = {7, 9, -1, 3, 4, 15, 7, 2}, n = 8, m = 5; for(int i = 0; i < m * n; i++){ // 重複 m * n 次 printf("%d%c", arr[i % n], " \n"[(i + 1) % n == 0]); } // 純炫技,看不懂請見諒,有興趣研究者歡迎詢問 ``` ---- **宣告陣列時歸零** ```cpp int arr[10000] = {0}; ``` ---- **輸入n個數字並找出[眾數](https://zh.wikipedia.org/zh-tw/%E4%BC%97%E6%95%B0_(%E6%95%B0%E5%AD%A6))** ```cpp int arr[105] = {0}, n, tmp; scanf("%d", &n); // 輸入n for(int i = 0; i < n; i++){ // 輸入 n 個數字 scanf("%d", &tmp); arr[tmp]++; // 編號 tmp 的位置 +1 } int mx = -1, ans = 0; // 找最大值 並用 ans 紀錄答案 for(int i = 0; i < 105; i++){ if(mx < arr[i]){ mx = arr[i]; ans = i; } } printf("眾數: %d, 出現%d次", ans, mx); ``` **注意這樣寫只能紀錄 0~104 的數字** <!-- .element: class="fragment" data-fragment-index="1" --> ---- <!-- .slide: data-transition="fade" --> **一維陣列操作還有很多很多...** **如果以上範例沒有你想要的** **歡迎自己研發新的寫法喔** --- <!-- .slide: data-transition="fade" --> ### 二維陣列 ---- <!-- .slide: data-transition="fade" --> **二維陣列就是他的idx有兩個** **一般來說就是用兩個[]表示** ---- <!-- .slide: data-transition="fade" --> **像arr[i][j] 就是arr陣列第i, j個位置** ![image](https://hackmd.io/_uploads/rJjGxct5R.png) **可以畫成網格狀來表示位置** ---- <!-- .slide: data-transition="fade" --> **有些網路上的文章會寫 i 稱為行(column) j 稱為列(row)** **跟我們在數學上的矩陣叫法一樣** <!-- .element: class="fragment" data-fragment-index="1" --> ---- <!-- .slide: data-transition="fade" --> <h3 class="text-left"> 二維陣列宣告 </h3> ```cpp int arr[105][15]; // 宣告一個 105 * 15 的陣列 ``` ---- <!-- .slide: data-transition="fade" --> <h3 class="text-left"> 二維陣列存取 </h3> ```cpp int arr[8][6]; // 宣告一個 8 * 6 的陣列 arr[5][4] = 87; // i=5, j=4 的位置 存入 87 arr[2][0] = 4; // i=2, j=0 的位置 存入 4 printf("%d", arr[5][[4]]); // 輸出 87 ``` <img src="https://hackmd.io/_uploads/rJyS0aYc0.png" style="width: 600px"> --- <!-- .slide: data-transition="fade" --> ### 奇奇怪怪的二維陣列操作 ---- <!-- .slide: data-transition="fade" --> **輸入輸出二維陣列** ```cpp int arr[8][6]; // 宣告一個 8 * 6 的陣列 for(int i = 0; i < 8; i++){ // column for(int j = 0; j < 6; j++){ // row scanf("%d", &arr[i][j]); // 輸入 arr[i][j] } } for(int i = 0; i < 8; i++){ // column for(int j = 0; j < 6; j++){ // row printf("%d ", arr[i][j]); // 輸出 arr[i][j] } printf("\n"); // 換行 } ``` ---- **宣告時就把數字塞入二維陣列** ```cpp int arr[3][6] = { {1, 2, 3, 4, 5, 6}, {2, 4, 6, 8, 10, 12}, {3, 6, 9, 12, 15, 18} }; ``` ---- <!-- .slide: data-transition="fade" --> **更多奇奇怪怪的用法 可以在動態規劃裡面看到** --- <!-- .slide: data-transition="fade" --> ### 例題練習 ---- <!-- .slide: data-transition="fade" --> [Zerojudge d786. 三、平均值](https://zerojudge.tw/ShowProblem?problemid=d786) [CSES Missing Number](https://cses.fi/problemset/task/1083) [Zerojudge b374. [福州19中]众数](https://zerojudge.tw/ShowProblem?problemid=b374) [Zerojudge g595. 1. 修補圍籬](https://zerojudge.tw/ShowProblem?problemid=g595) [Zerojudge g498. 兔子跳躍 (Rabbit)](https://zerojudge.tw/ShowProblem?problemid=g498) [Zerojudge c638. 天干地支](https://zerojudge.tw/ShowProblem?problemid=c638) [Zerojudge m398. 超市排隊 (Supermarket)](https://zerojudge.tw/ShowProblem?problemid=m398) [Zerojudge c561. Bert 愛搗蛋](https://zerojudge.tw/ShowProblem?problemid=c561) ---- [CSES Number Spiral](https://cses.fi/problemset/task/1071) [Zerojudge e798. p5. 卷積神經網路](https://zerojudge.tw/ShowProblem?problemid=e798) [Zerojudge a015. 矩陣的翻轉](https://zerojudge.tw/ShowProblem?problemid=a015) [Zerojudge b266. 矩陣翻轉](https://zerojudge.tw/ShowProblem?problemid=b266) [Zerojudge e339. 前綴和練習](https://zerojudge.tw/ShowProblem?problemid=e339) [Zerojudge c292. APCS2017-0304-3數字龍捲風](https://zerojudge.tw/ShowProblem?problemid=c292) **要用億點點數學跟前面學過的內容喔** <!-- .element: class="fragment" data-fragment-index="1" --> ---- **PS: 這章節的練習題有點刁難初學者 \><** --- <!-- .slide: data-transition="fade" --> ### 以上就是本章節的內容
{"description":"認識陣列","title":"C程式設計導論-陣列","contributors":"[{\"id\":\"4f67a8cd-06ae-45dc-a8e3-62c6a41e5a37\",\"add\":8533,\"del\":597}]"}
    209 views