陣列與基本算法

陣列概念、基本操作、加總、平均、線性檢索、點算、最大 / 最小值、插入及刪除。

索引起點(Index Base)
目前:由 1 開始(1-based)

3.2 陣列是甚麼?為甚麼不使用一大堆變量?

1️⃣ 一個個變量的問題

如果要儲存 5 個學生分數,用 h1, h2, h3, h4, h5 當然可以,但:

2️⃣ 陣列 = 一排有次序的「格」

陣列可以儲存一組同類型的數據,例如全部都是分數。每一格都有一個索引 index, 慣用由 1 開始:array[1]array[2]……。

下面以一個示範陣列 array[ ] 展示「項目行」與「索引行」分開兩行的效果:

索引起點(Index Base)

本頁預設使用 1-based(索引行顯示為 1、2、3⋯)。你可切換至 0-based(索引行顯示為 0、1、2⋯)以對照不同語言慣例。

之後所有示範都會用相同的方式顯示陣列:上面一行是每一格的內容,下面一行是索引。

3️⃣ 陣列同循環的關係

大部分處理陣列的算法都是:

設 i ← 1 至 N
重複
  (處理 array[i])
  i ← i + 1
直至 i > N

之後每一個小遊戲,其實都是在這個「由 1 行到 N」的框架之內,加上不同的處理步驟。

3.2b 陣列基本操作:輸入與輸出

本部分希望學生真正明白:

A. 由鍵盤輸入 5 個分數到 array[ ]

請輸入 5 位同學的分數:

array[ ] 陣列(上行:項目,下行:索引):

對應偽代碼(輸入 5 個分數)

重點:用一個循環變量 i 重複輸入 array[i],就可以一氣呵成輸入多個值。

B. 從偽代碼讀出整個陣列內容

下面會隨機產生一段 array[ ] 陣列的「賦值」偽代碼,請你根據代碼寫出陣列每一個項目的數值。

按「重新出一題偽代碼」開始 😊

請填寫你讀到的陣列內容:

填空小測:陣列輸入 / 輸出

提示:只需要填「空格」內容;不需要輸入偽代碼的箭咀(←)。

按「下一題」開始 😊

3.3a 陣列加總:計算總分數 total

常見題目:把一班同學的分數全部加起來,儲存在變量 total

偽代碼(四種循環版本)

total ← 0
設 i 由 1 至 N
  total ← total + array[i]
輸出 total
total ← 0
i ← 1
當 i ≤ N
  total ← total + array[i]
  i ← i + 1
輸出 total
total ← 0
i ← 1
執行
  total ← total + array[i]
  i ← i + 1
當 i ≤ N
輸出 total
total ← 0
i ← 1
重覆
  total ← total + array[i]
  i ← i + 1
直至 i > N
輸出 total

先「清零」 total,再用循環由 array[1] 加到 array[N],每一圈更新一次 total。

用 array[ ] 陣列做示範

這個陣列會跟隨你在「輸入 5 個分數」部分輸入的數值;如果尚未輸入,就會使用示範數據。

目前 total = 0,目前 i = -

逐步運行加總算法

每按一次「下一步」,就會把 array[i] 加入 total,同時 i 加 1。

小問題:循環變量一定要叫 i 嗎?

請輸入一個你覺得合用的計數變量名稱(例如 ik):

重點:變量名可以自由選擇,但同一段偽代碼內要前後一致(設 i ← 1 至 N、array[i]、i ← i + 1)。

小測:陣列加總
按「下一題」開始 😊
填空小測:陣列加總

提示:只需要填「空格」內容;不需要輸入偽代碼的箭咀(←)。

按「下一題」開始 😊

3.3b 陣列平均值:計算平均分數 average

計算平均分數時,先把所有分數加總,再除以人數 N。

偽代碼(四種循環版本)

total ← 0
設 i 由 1 至 N
  total ← total + array[i]
average ← total / N
輸出 average
total ← 0
i ← 1
當 i ≤ N
  total ← total + array[i]
  i ← i + 1
average ← total / N
輸出 average
total ← 0
i ← 1
執行
  total ← total + array[i]
  i ← i + 1
當 i ≤ N
average ← total / N
輸出 average
total ← 0
i ← 1
重覆
  total ← total + array[i]
  i ← i + 1
直至 i > N
average ← total / N
輸出 average

此處不假設「已經有 total」,而是由零開始寫出加總 + 除 N 的完整算法。

步驟一定是:① total 清零 → ② 用循環把全部項目加起來 → ③ 用 total / N。

示範陣列

目前 total = 0,目前 i = -

目前 average = -

逐步運行平均值算法

每按一次「下一步」會先逐格加總;加總完成後再按一次,會計算 average = total / N

小測:陣列平均值
按「下一題」開始 😊
填空小測:平均值

提示:只需要填「空格」內容;不需要輸入偽代碼的箭咀(←)。

按「下一題」開始 😊

3.4b 點算符合條件的項目數目(count)

很多題目需要「點算」有多少個項目符合某個條件,例如:

偽代碼(四種循環版本)

count ← 0
設 i 由 1 至 N
  如果 array[i] > bound 則
    count ← count + 1
輸出 count
count ← 0
i ← 1
當 i ≤ N
  如果 array[i] > bound 則
    count ← count + 1
  i ← i + 1
輸出 count
count ← 0
i ← 1
執行
  如果 array[i] > bound 則
    count ← count + 1
  i ← i + 1
當 i ≤ N
輸出 count
count ← 0
i ← 1
重覆
  如果 array[i] > bound 則
    count ← count + 1
  i ← i + 1
直至 i > N
輸出 count

關鍵:count 一開始必須是 0,之後每遇到一個符合條件就加 1。

示範陣列

逐步點算高於 bound 的人數

請設定界線值 bound,按「開始」後再用「下一步」逐格檢查:

目前 i = -,目前 array[i] = -

目前 count = 0

結果:有 0 位同學分數高於 bound。

小測:點算符合條件項目數
按「下一題」開始 😊
填空小測:點算

提示:只需要填「空格」內容;不需要輸入偽代碼的箭咀(←)。

按「下一題」開始 😊

3.4c 最大值 / 最小值:打擂台做比較

以「打擂台」作比喻:先假設第一個項目是冠軍,之後每個挑戰者都與它比較,勝出的就取代它。

偽代碼(可選擇最大值或最小值,並切換四種循環)

champion ← array[1]
設 i 由 2 至 N
  如果 array[i] > champion 則
    champion ← array[i]
輸出 champion
champion ← array[1]
i ← 2
當 i ≤ N
  如果 array[i] > champion 則
    champion ← array[i]
  i ← i + 1
輸出 champion
champion ← array[1]
i ← 2
執行
  如果 array[i] > champion 則
    champion ← array[i]
  i ← i + 1
當 i ≤ N
輸出 champion
champion ← array[1]
i ← 2
重覆
  如果 array[i] > champion 則
    champion ← array[i]
  i ← i + 1
直至 i > N
輸出 champion

提示:兩者的做法相同,只需把比較符號由 > 改為 <(或相反)即可。

示範陣列

逐步尋找最高 / 最矮

請選擇要找「最高」還是「最矮」,再按「開始」及「下一步」。

目前冠軍值 champion = -

目前 i = -

提示:最大值用 >,最小值用 <

小測:最大值 / 最小值
按「下一題」開始 😊
填空小測:最大值 / 最小值

提示:只需要填「空格」內容;不需要輸入偽代碼的箭咀(←)。

按「下一題」開始 😊

3.5 檢查陣列是否已排序

本節示範如何檢查一個陣列是否已按指定方向排序(由小至大 / 由大至小)。

示範陣列 A(大致由小至大)

示範陣列 B(包含亂序)

試試用下面的檢查,看看 A / B 是否按指定方向排序。

偽代碼(可選擇排序方向,並切換四種循環)

sorted_list ← True
設 i 由 1 至 N − 1
  如果 list[i] > list[i + 1] 則
    sorted_list ← False
輸出 sorted_list
sorted_list ← True
i ← 1
當 (i ≤ N − 1) 且 (sorted_list = True)
  如果 list[i] > list[i + 1] 則
    sorted_list ← False
  i ← i + 1
輸出 sorted_list
sorted_list ← True
i ← 1
執行
  如果 list[i] > list[i + 1] 則
    sorted_list ← False
  i ← i + 1
當 (i ≤ N − 1) 且 (sorted_list = True)
輸出 sorted_list
sorted_list ← True
i ← 1
重覆
  如果 list[i] > list[i + 1] 則
    sorted_list ← False
  i ← i + 1
直至 (i > N − 1) 或 (sorted_list = False)
輸出 sorted_list

提示:兩種方向的差異只在比較符號;由小至大使用 >,由大至小使用 <

選擇陣列、方向,用算法檢查排序(一次過 / 逐步)
陣列: 排序方向:

目前 i = -(比較 list[i]list[i+1]

逐步版每按一次會比較一對相鄰元素;一旦發現亂序就會停止。

操作示範:為甚麼 i 要由第一個索引走到最後第二個索引?為甚麼比較 list[i]list[i+1]

要檢查陣列是否已按「由小至大」排序,關鍵在於:每一對相鄰元素都必須符合次序(即 list[i] ≤ list[i+1])。 因此,排序檢查只需要逐對比較相鄰元素即可。 同時,因為每一步都會用到 list[i+1],所以 i 的最大值必須是「最後第二個索引」; 若把終止值寫到最後一個索引(甚至寫到 N),就會在某一輪嘗試存取不存在的 list[i+1] 而越界。

下方工具讓你自行設定 i 的起始值與終止值,並可選擇四種循環版本,觀察會否出現「漏檢」或「索引越界」。
提示:N 代表陣列長度;索引顯示會按本頁上方的「Index Base」設定自動切換。

陣列: 方向: 循環版本:
先看清楚示範陣列(上行是數值,下行是索引)。你在下方空格輸入的起始值/終止值會對應到這行索引。
本次陣列長度 N = -
sorted_list ← True
設 i 由
  如果 list[i] > list[i+1] 則
    sorted_list ← False
輸出 sorted_list
(可在空格輸入整數;亦可輸入 n 代表 N,例如:n-1n。)

目前 i = -(比較 list[i]list[i+1]

(尚未開始。)

提示:若把終止值設為 N,最後一輪會嘗試比較 list[N]list[N+1],因此會越界;若把終止值設為 N−2,則最後一對 (N−1, N) 不會被檢查。

小測:檢查是否已排序
按「下一題」開始 😊
填空小測:排序檢查

提示:只需要填「空格」內容;不需要輸入偽代碼的箭咀(←)。

按「下一題」開始 😊

3.5a 刪除陣列項目

本節示例不預先假設 array[ ] 已經排序。重點是學習如何刪除第 P 個項目, 並把其後數據向左移動一格,最後更新 N

共同示範陣列

以下以這組 array[ ] 作刪除示範:

顯示方式與前文相同:上行是 array[ ] 的各項目,下行是索引(1、2、3⋯)。

刪除第 P 個項目(向左移動)

偽代碼(四種循環版本)

輸入 P
如果 P ≤ N − 1 則
  設 i 由 P至 N − 1
    array[i] ← array[i + 1]
N ← N − 1
輸入 P
如果 P ≤ N − 1 則
  i ← P
  當 i ≤ N − 1
    array[i] ← array[i + 1]
    i ← i + 1
N ← N − 1
輸入 P
如果 P ≤ N − 1 則
  i ← P
  執行
    array[i] ← array[i + 1]
    i ← i + 1
  當 i ≤ N − 1
N ← N − 1
輸入 P
如果 P ≤ N − 1 則
  i ← P
  重覆
    array[i] ← array[i + 1]
    i ← i + 1
  直至 i > N − 1
N ← N − 1
刪除位置 P:

目前 i = -

操作示範:理解「設 iP最後第二個索引」的原因(可自行輸入 P 與循環範圍)

刪除第 P 個項目時,核心動作是把 P 後面的元素逐格向左移(把右邊的值覆蓋到左邊)。 在偽代碼中,這一步通常寫成 array[i] ← array[i+1]。 因此循環必須由 i = P 開始,否則無法覆蓋 array[P] 這一格。

又因為每一步都會用到 array[i+1],所以 i 的最大值必須是「最後第二個索引」(即最後一格之前那一格)。 若把終止值寫到最後一個索引(或寫到 N),就會在某一輪嘗試存取不存在的 array[i+1] 而產生「索引越界」。

(1) 為甚麼循環起點要寫 P

P 代表「你想刪除的位置」。刪除的核心做法,是把第 P 格之後的元素逐格向左搬, 令 array[P]array[P+1] 覆蓋。若循環不是由 P 開始,就無法保證刪除的正是你指定的第 P 個項目。

更重要的是:如果你在循環起點填了固定數字(例如 1、2、3),即使上面輸入了 P,程式也不會使用它; 結果會變成「永遠刪除固定位置」或出現不完整移位。這就是為甚麼空格通常要填 P

(2) 操作示範:在循環空格填入不同內容,觀察會發生甚麼事

你可以在下列空格輸入:1~7;或 p(代表上方輸入的 P);或 n(代表陣列長度 N)。系統會在執行時自動代入對應數值。
提示:N 代表陣列長度;索引顯示會按本頁上方的「Index Base」設定自動切換。

目標刪除位置 P: 循環版本: 示範陣列長度 N: -
先看清楚示範陣列(上行是數值,下行是索引)。你輸入的 P(要刪除的位置)以及 i 的起止值,都是根據這行索引而定。
輸入 P
如果 P ≤ N − 1 則
  設 i 由
    array[i] ← array[i+1]
N ← N − 1

目前 i = -(執行 array[i] ← array[i+1]

(尚未開始。)

3.5b 插入陣列項目

插入新項目時,需要先「騰出空位」:把第 P 個位置及其後的數據向右移動一格, 再把新值 H 放入 array[P]

目前的示範陣列

插入/刪除操作會即時更新下表:

在第 P 個位置插入新分數 H(向右移動)

偽代碼(四種循環版本)

輸入 H, P
N ← N + 1
設 i 由 N 下至 P + 1
  array[i] ← array[i − 1]
array[P] ← H
輸入 H, P
N ← N + 1
i ← N
當 i ≥ P + 1
  array[i] ← array[i − 1]
  i ← i − 1
array[P] ← H
輸入 H, P
N ← N + 1
如果 P ≤ N − 1 則
  i ← N
  執行
    array[i] ← array[i − 1]
    i ← i − 1
  當 i ≥ P + 1
array[P] ← H
輸入 H, P
N ← N + 1
如果 P ≤ N − 1 則
  i ← N
  重覆
    array[i] ← array[i − 1]
    i ← i − 1
  直至 i < P + 1
array[P] ← H
新分數 H:
插入位置 P:

目前 i = -

操作示範:理解「把元素向右移:i 由尾端下至 P+1」的原因(並觀察「下至」與「至」的差異)

插入新值的本質,是先把 P最後一個索引的元素整段向右移一格,騰出 array[P] 的空位。 為避免「尚未搬走的資料」被覆蓋,搬移必須由尾端開始,因此循環方向必須是由大至小下至 / DOWNTO)。

本工具會先執行「N ← N+1(加長一格)」再進行移位。你可自行改動 i 的起點、終點及方向,觀察會否出現「漏搬」、「覆蓋」或「索引越界」。

插入值 H: 插入位置 P: 循環版本:
先看清楚示範陣列(上行是數值,下行是索引)。你輸入的 P 以及 i 的起止值,都是根據這行索引而定。
插入前 N = -;執行 N ← N+1 後,新 N = -
輸入 H, P
N ← N + 1
設 i 由
  array[i] ← array[i−1]
array[P] ← H

你可以在空格輸入整數;亦可輸入 n 代表「新 N(陣列長度)」、輸入 p 代表 P,例如:np+1注意:在 0-based 的情況下,最後一個索引是 n−1,因此「標準起點」通常會寫成 n−1。 若你選擇「至(由小至大)」但起點大於終點,系統會自動把起點與終點對調,以符合「至」的方向。

目前 i = - (移位步驟執行 array[i] ← array[i−1];移位完成後才會執行 array[P] ← H。)

(尚未開始。)

重點提示: (a) 起點必須使用「更新後的最後一個索引」(即加長後最尾那一格),否則最後一格無法被正確搬移; (b) 必須使用「下至」才不會在向右搬移時覆蓋尚未搬走的資料; (c) 終點通常寫作 P+1,因為 P+1 才是第一個需要接收舊 array[P] 的位置。 若把終點寫到 P,在不少情況下仍可得到正確結果,但會多做一步把 array[P−1] 複製到 array[P],而該格隨後又會被 array[P] ← H 覆蓋,所以屬於沒有意義的額外工作。 不過,當 P 等於最小合法索引(1-based:P=1;0-based:P=0)時,終點若寫成 P 會令循環最終嘗試讀取 array[P−1](例如 array[0]array[-1]),從而造成越界。

小測:插入 / 刪除
按「下一題」開始 😊
填空小測:插入及刪除

提示:只需要填「空格」內容;不需要輸入偽代碼的箭咀(←)。

按「下一題」開始 😊

3.6 綜合練習:代碼辨認 + 填充語句漏空

本部分會綜合本頁學過的算法(加總、平均值、線性檢索、點算、最大/最小值、排序檢查、插入、刪除),並提供「辨認代碼」及「補空」題目。

綜合小測(隨機抽題)
按「下一題」開始 😊

3.7 Check Point 小測:多項選擇題

本節把本章重點整理為多項選擇題。每題均附解釋,而且所有選項均由題庫 JSON 檔案動態載入,並可按需要隨機排序,方便反覆練習。

使用方法:按「下一題」抽出題目;選擇答案後系統會即時顯示正誤及解釋。你可重覆練習直至掌握為止。

CP1 陣列概念與基本輸入/輸出

Check Point 1
請按「下一題」開始。

CP2 陣列加總與平均值

Check Point 2
請按「下一題」開始。

CP3 線性檢索與點算

Check Point 3
請按「下一題」開始。

CP4 最大/最小、排序檢查、插入與刪除

Check Point 4
請按「下一題」開始。