🧠 主題 7:演算法設計與問題解決 💡

各位未來的電腦科學家好!這一章是整個課程中最重要的一章。為什麼呢?因為程式設計不僅僅是輸入代碼,它更是關於運用「邏輯思考」來解決問題。
我們將學習專業人士如何將一個模糊的構想,一步步轉化為能運作的電腦程式。就把這當作在開始烹飪前學習一份食譜吧!

1. 程式開發生命週期 (PDLC) (7.1)

當你要建立一個電腦系統時,不能直接跳進去寫代碼。你需要一個結構化的計劃,這個計劃稱為程式開發生命週期 (Program Development Life Cycle, PDLC)。它有四個主要階段:

階段 1:分析 (問題是什麼?)

在這個階段,你需要明確找出系統具體要做什麼。如果你在這裡弄錯了問題,整個程式都會是錯的!

  • 識別問題與需求: 會使用什麼數據?使用者是誰?系統必須達成什麼目標?
  • 抽象化 (Abstraction): 這意味著隱藏不必要的細節,只呈現最重要的資訊。
    例子:當你看城市地圖時,你看到的是主要道路和地標,而不是每一棵樹或坑洞。這就是抽象化——專注於重要事物(路徑)。
  • 分解 (Decomposition): 將一個大型且複雜的問題,拆解成較小、易於管理的部分(子系統)。
    例子:製造機械手臂太龐大了,將其分解為:1. 手部動作控制、2. 手腕旋轉、3. 底座穩定。
階段 2:設計 (我們將如何解決問題?)

在這個階段,你在寫任何代碼之前先規劃好逐步解決方案。你會使用流程圖 (Flowchart) 和虛擬碼 (Pseudocode) 等工具。

  • 分解: (這裡再次使用!) 我們將系統拆解為模組(子系統),這有助於我們分別設計每個部分。
  • 結構圖 (Structure Diagrams): 展示主系統如何劃分為模組和子模組。
  • 流程圖 (Flowcharts): 一種使用標準符號(如處理、輸入/輸出、判斷等)來展示邏輯流程的圖形化方式。
  • 虛擬碼 (Pseudocode): 用於描述演算法的結構化英語。它使用程式設計關鍵字,但不綁定特定的程式語言。

💡 核心概念:IPOS 結構 (7.2)
在設計任何模組時,請務必考慮 IPOS 結構:
  • Inputs (輸入):進入此模組的數據是什麼?
  • Processes (處理):進行了什麼計算或邏輯?
  • Outputs (輸出):顯示或產生了什麼資訊?
  • Storage (儲存):需要保存什麼數據(例如在變數或檔案中)?

階段 3:編碼 (編寫解決方案)

這是將計劃(虛擬碼/流程圖)使用高階語言(如 Python 或 Java)轉換為實際程式碼的階段。此階段還包括反覆測試 (Iterative Testing)——即在編寫代碼時同步測試較小的程式部分。

階段 4:測試 (我們是否正確解決了問題?)

你使用各種類型的測試數據 (Test Data) 來執行程式,以確保它能按照需求運作,並能妥善處理未預期的情況。


重點總結: PDLC 確保你在開始編程前完全理解問題,這能節省日後大量的時間。分析與設計對於編寫優質程式至關重要!

2. 標準解決方法 (演算法) (7.4)

某些任務在程式設計中非常普遍,因此有標準且廣為人知的解決方案。你必須理解並能描述這些算法:

1. 加總與計數

這是最簡單的演算法。

  • 計數 (Counting): 用於追蹤事件發生的次數。你需要一個計數器變數,初始值為 0,每發生一次事件就加 1。(例如:統計得分超過 80% 的學生人數。)
  • 加總 (Totalling): 用於累加數值總和。你需要一個總和變數(累加器),初始值為 0,在每次迴圈中加入新的數值。(例如:計算購物車中商品的總價。)
2. 找尋最大值、最小值與平均值

要找最大值/最小值,你通常會假設輸入的第一個值即為最大(或最小)值,然後將隨後的每個值與之比較,如果發現更大或更小的值,就更新你的變數。

  • 平均值: \( \text{Average} = \frac{\text{Total}}{\text{Count}} \)
3. 線性搜尋 (順序搜尋)

透過從頭到尾逐一檢查列表(陣列)中的每個項目,來尋找特定目標。

  • 運作方式: 從位置 1 開始。將搜尋值與列表中的項目進行比較。如果相符則停止;如果不相符,則移動到下一個位置。重複此過程直到找到目標或到達列表末尾。
  • 你知道嗎? 這個方法很簡單,但對於很長的列表來說速度很慢。
4. 氣泡排序 (Bubble Sort)

用於將列表項目進行排序(升序或降序)。之所以叫氣泡排序,是因為最大(或最小)的值會像氣泡一樣「浮」到正確位置。

  • 運作方式: 重複遍歷列表,比較相鄰元素,如果順序錯誤則交換它們。此過程會重複直到整個過程都不需要交換為止,代表列表已排序完成。
  • 類比: 想像汽水杯中實際的氣泡。最大、最輕的氣泡會隨著反覆的擾動最終上升到頂部。

重點總結: 這些標準演算法是大多數程式的基石。請務必練習如何為氣泡排序或線性搜尋編寫虛擬碼!

3. 數據完整性:驗證 (Validation) 與核實 (Verification) (7.5 & 7.6)

數據完整性意味著確保數據準確且合理。我們主要使用兩種方法:驗證與核實。

3.1 數據驗證 (Data Validation) (7.5)

驗證 (Validation) 是檢查輸入的數據是否合理 (Reasonable)有意義 (Sensible),但它不能保證數據 100% 正確。

  • 範圍檢查 (Range Check): 檢查輸入是否在預設的最大值和最小值範圍內。
    例子:測試分數必須在 0 到 100 之間。
  • 長度檢查 (Length Check): 檢查數據是否包含所需數量的字元。
    例子:密碼必須正好 8 個字元長。
  • 類型檢查 (Type Check): 檢查輸入的數據類型是否正確。
    例子:數量欄位必須輸入 INTEGER(整數),不能輸入文字。
  • 存在檢查 (Presence Check): 檢查欄位中是否已輸入數據(即欄位不能留空)。
    例子:姓名欄位不能為空。
  • 格式檢查 (Format Check): 檢查數據是否符合特定的格式或結構。
    例子:英國郵遞區號格式必須為 'LLNN NLL' (如 SW1A 0AA)。
  • 檢查位元 (Check Digit): 從數字的其他位元計算出的額外數字(如 ISBN 或條碼)。它能確保輸入錯誤(如打字錯誤)被檢測出來。

🧠 記憶小撇步:驗證就是檢查「合理性」!
記住 V.A.L.I.D.A.T.I.O.N.,這些檢查是為了確保數據是合理 (Reasonable) 的,但不一定保證數據正確。

3.2 數據核實 (Data Verification) (7.6)

核實 (Verification) 是檢查輸入系統的數據是否與原始來源數據一致。它確保在數據傳輸或輸入過程中的準確性。

  • 視覺檢查 (Visual Check): 使用者直接對照螢幕上的輸入內容與原始來源文件(例如檢查表格)。
  • 雙重輸入檢查 (Double Entry Check): 數據輸入兩次,可能由不同人輸入,或由同一人輸入兩次。電腦會比較兩次輸入結果,如果相符,則接受該數據。

重點總結: 驗證檢查輸入是否「可能」(例如:99 分是一個可能的分數嗎?);核實檢查輸入是否「準確」(例如:紙上寫的是 96 分,我是否有誤打成 99 分?)。

4. 測試與除錯 (7.7 & 7.8)

好的程式必須經過徹底測試。我們需要使用特定的測試數據類型,以確保程式能處理所有狀況。

4.1 測試數據類型 (7.7)
  • 正常數據 (Normal Data): 預期中的、有效的,且在可接受範圍內的數據。
    例子:如果有效範圍是 1 到 100,正常數據可以是 50。
  • 邊界數據 (Boundary/Extreme Data): 位於可接受範圍邊緣的數據,以及最大/最小的不可接受值。
    例子:若 1 到 100 有效,測試 1 和 100(邊界值),以及 0 和 101(無效的邊界值)。
  • 異常數據 (Abnormal Data): 完全無效、且超出預期類型或範圍的數據。
    例子:在預期 1 到 100 的數字欄位中輸入 "potato"。
4.2 追蹤表 (Trace Tables / Dry Runs) (7.8)

追蹤表 是手動檢查演算法邏輯的重要工具(此過程稱為 乾跑 (Dry Run))。

  • 為演算法中使用的每個變數建立欄位,並為任何輸出使用者提示建立欄位。
  • 逐步執行演算法,隨著變數值的改變更新表格中的數值。
  • 這有助於你在編寫實際代碼前,發現設計中的邏輯錯誤(臭蟲)。

如果剛開始覺得這有點難,別擔心;透過簡單的迴圈和選擇語句多加練習,追蹤表會變得非常容易!

4.3 解釋演算法用途 (7.3)

在考試中,你可能會被要求解釋某個演算法的功能。你的答案必須包含兩部分:

  1. 說明目標: 清晰定義該演算法的目標 (例如:「該演算法找出使用者輸入的最大值。」)
  2. 描述處理過程: 解釋它是「如何」達成目標的 (例如:「它使用迴圈讀取 10 個輸入,將每個輸入與名為 MaxValue 的變數比較,如果新輸入值較大,則更新 MaxValue。」)

重點總結: 測試需要使用不同類型的數據進行刻意練習。追蹤表是你用來查找邏輯錯誤的「手動」方法。