學習筆記:陣列與列表 (基礎數據結構 3.2.1)

歡迎!本章節是你在電腦科學中高效組織數據的基石。陣列(Arrays)和列表(Lists)是我們儲存一系列項目最基本、最根本的方式。掌握它們至關重要,因為幾乎所有實用的程式——從排序演算法到電子遊戲——都依賴於將數據組織成結構化的群組。

如果起初覺得這些概念有些抽象,也不用擔心。你可以把數據結構想像成不同類型的文件櫃——它們都能儲存資訊,但有些適合快速存取(例如陣列),而有些則適合彈性擴充(例如列表)。

1. 理解數據結構:背景知識 (3.2)

數據結構 (Data structure) 簡單來說,就是一種在電腦中組織數據的特定方式,以便能高效地使用。在深入研究陣列和列表之前,我們需要先釐清一個關鍵區別:

靜態與動態數據結構

主要區別在於程式執行(runtime)期間,其空間大小的靈活性。

  • 靜態數據結構 (例如:陣列)

    當結構被建立時,其大小就已經固定了。在程式執行期間,它無法增加或縮減。可以把它想像成一個預先訂好的披薩盒——它剛好有 8 片,不多也不少。

    優點: 記憶體使用非常高效,存取時間更快,因為電腦確切知道每個數據儲存的位置。

    缺點: 缺乏靈活性。如果空間不足,你必須建立一個全新的、更大的結構,並將所有數據複製過去。


  • 動態數據結構 (例如:列表,常在 Python 中見到)

    大小是靈活的,可以在程式執行時隨意變動(增加或縮減)。可以把它想像成購物袋——你可以不斷放入商品直到裝滿,或者輕鬆地取出它們。

    優點: 高度靈活;記憶體使用會隨著儲存的數據量動態調整。

    缺點: 與靜態結構相比,存取元素或管理記憶體的速度可能稍慢,因為元素在記憶體中的儲存位置未必完全連續。

重點總結: 當你預先知道數據的上限時,請使用靜態結構(陣列);當數據量無法預測或不斷變化時,請使用動態結構(列表)。

2. 陣列與列表:核心概念 (3.2.1)

陣列和列表的目的都是為了在一個識別碼(名稱)下儲存多個數值。

什麼是陣列 (Array)?

陣列是一組數據項的集合,通常屬於相同的數據類型,並儲存在記憶體中連續(相鄰)的位置。這種結構允許對任何元素進行快速、隨機的存取。

類比:想像一排編了號的郵政信箱。每個信箱(元素)存放一個項目,且它們按順序排列。

關鍵概念:索引 (Indexing)

要存取陣列或列表中的項目,我們使用它的索引(位置編號)。

  • 在大多數電腦科學情境(及程式語言)中,索引從零 (0) 開始。
  • 如果一個陣列有 \(N\) 個項目,索引範圍即為 \(0\) 到 \(N-1\)。

常見錯誤警告 (差一錯誤, Off-by-One Error): 學生經常忘記索引是從 0 開始的。如果你嘗試存取列表中從 1 開始的第 10 個項目,你將會拿到錯誤的數據。如果你嘗試存取等於陣列大小的索引(例如:在大小為 5 的陣列中存取索引 5),你將會導致執行時期錯誤(Index Out of Bounds,索引超出範圍)。

記憶技巧: 如果你想找第 1 個項目,請搜尋索引 0。如果你想找第 5 個項目,請搜尋索引 4。你想要的位置永遠是 index - 1

列表 (List) 的定義 (以及程式設計背景)

雖然陣列通常被視為固定大小且類型單一的結構,但在許多高階語言中(如課程大綱中提到的 Python),列表 (List) 一詞被用來描述更靈活、動態的結構,通常可以容納多種數據類型,並能輕鬆改變大小。

重要的考試筆記: 在程式設計考試中,除非題目特別要求靜態陣列的特性,否則通常可以使用該語言內建的 List 類型來解決問題。

3. 操作一維 (1D) 結構

一維陣列/列表代表單行或序列的數據。定位一個元素只需要一個索引。

逐步教學:存取元素
  1. 識別陣列/列表名稱: 讓我們稱之為 Student_Names
  2. 確定索引: 如果我們想要第 3 個名字,索引就是 2。
  3. 存取元素:

    Student_Names[2] 將會提取儲存在該位置的數值。

使用範例:

假設我們有一個測驗分數列表:
Scores = [90, 85, 95, 78, 92]

  • Scores 的長度為 5。
  • 最低索引為 0,最高索引為 4。
  • 要找到 85,我們存取 Scores[1]。

4. 二維 (2D) 陣列與列表中的列表 (3.2.1)

通常數據不只是一條直線;它可能是一個網格或表格。這時二維陣列(或列表的列表)就非常重要。二維陣列是一個每個元素本身也是陣列的陣列。

類比:想像一個標準的試算表(如 Excel)。它有「行 (Rows)」和「列 (Columns)」。

結構與索引

要存取二維結構中的元素,你需要兩個索引

  1. 行 (Row) 的索引。
  2. 該行內 列 (Column) 的索引。

格式: ArrayName[RowIndex][ColumnIndex]

範例:座位表

想像一個小型電影院的座位表(3 行,每行 4 個座位):

Seats = [ [A1, A2, A3, A4], [B1, B2, B3, B4], [C1, C2, C3, C4] ]

  • A 行在索引 0,B 行在索引 1,C 行在索引 2。
  • 座位 1 在索引 0,座位 4 在索引 3。

如果你想要 B3 座位:

  • B 是第 2 行(索引 1)。
  • 3 是第 3 個座位(索引 2)。
  • 你會存取:Seats[1][2],這會得到 'B3'。
二維結構的應用

二維陣列經常被用於解決涉及以下方面的問題:

  • 數學中的矩陣 (Matrices)(例如:用於圖形變換)。
  • 遊戲棋盤(例如:國際象棋、數獨、儲存地圖的地形)。
  • 簡單黑白圖像的像素數據(此時二維即為高度和寬度)。

你知道嗎? 雖然課程大綱的測試範圍限制在二維,但程式語言支援多維陣列(例如用於空間數據的三維陣列或四維陣列),它們都是建立在將結構嵌套在一起的相同原則之上。

5. 操作陣列與列表

雖然具體的語法因語言而異,但你必須理解的基本操作如下:

存取與修改

你可以讀取特定索引處的數值,也可以修改該處的數值。

範例:修改分數

如果 Scores[0] = 90,而學生的分數進步到 98,你會使用賦值敘述 (assignment statement) 來修改該數值:

Scores[0] = 98

遍歷結構

為了處理陣列中的每一個項目(元素),你通常會使用迭代 (iteration)(即迴圈)。

  • 對於一維陣列:單一迴圈就足夠了,通常從索引 0 執行到陣列長度(但不包含該長度)。
  • 對於二維陣列:你需要巢狀迭代 (nested iteration)(迴圈中的迴圈)。外層迴圈通常控制行,內層迴圈控制該行中的列。

逐步教學:遍歷二維陣列

想像列印出一個 3x4 陣列的所有元素:

  1. 啟動外層迴圈(用於行 i = 0 到 2)。
  2. 在內部,啟動內層迴圈(用於列 j = 0 到 3)。
  3. 處理 Array[i][j] 的項目。
  4. 內層迴圈結束;移動到下一行(增加 i)。
  5. 重複上述步驟,直到所有行都被處理。

重點總結: 陣列與列表提供了有組織的儲存方式。一維結構使用一個索引;二維結構(網格/表格)使用兩個索引(先行,後列)。理解索引(從 0 開始!)對於避免錯誤至關重要。


***

準備好繼續前進了嗎?這些基礎結構為我們在接下來的章節中理解更複雜的數據結構(如記錄、佇列和堆疊)奠定了基礎!