## 二、 程式的創建流程(瀑布模型) 程式開發通常遵循以下步驟: 1. **需求收集**:確定系統所需的功能、目標與限制。 2. **系統分析**:深入理解需求,定義系統必須達成的標準。 3. **設計**: * **架構設計**:確立系統的整體結構與組件關係。 * **細節設計**:決定具體的資料結構、資料型態和演算法。 * **介面設計(可選)**:規劃使用者與系統的互動方式。 4. **編碼與調整**:將設計實現為程式碼,並進行初步優化。 5. **驗證與測試**:確保程式功能正確,符合所有需求。 6. **維護與演進**:持續進行錯誤修正、功能改進和系統升級。 ----- ## 三、 演算法(Algorithm) ### 1\. 定義 演算法是**一組有限且定義清晰的指令**,用於完成特定任務或解決特定問題。 ### 2\. 特性 演算法必須滿足以下五個特性: * **輸入 (Input)**:具備零個或多個輸入。 * **輸出 (Output)**:至少產生一個或多個輸出。 * **確定性 (Definiteness)**:每條指令都必須清晰、無歧義。 * **有限性 (Finiteness)**:演算法必須在有限的步驟後終止。 * **有效性 (Effectiveness)**:每個指令都必須是基本、可行且可在有限時間內完成的。 ----- ## 四、 遞迴(Recursion) ### 1\. 定義 遞迴是指在程式中,一個函數**直接或間接呼叫自身**的機制。 ### 2\. 種類 * **直接遞迴 (Direct Recursion)**:函數 $A$ 直接呼叫函數 $A$。 * **間接遞迴 (Indirect Recursion)**:函數 $A$ 呼叫函數 $B$,而函數 $B$ 再呼叫函數 $A$。 * **尾遞迴 (Tail Recursion)**:遞迴呼叫是函數中最後一個執行的操作。 ### 3\. 優點與缺點 | 項目 | 優點 | 缺點 | | :--- | :--- | :--- | | **程式碼** | 邏輯清晰,易於設計與閱讀,程式碼簡潔。 | 執行效率較低,且需要消耗較多的**堆疊空間**(Stack Space)來儲存中間狀態。 | ### 4\. 常見應用 * **數學問題**:如階乘 ($N!$)、費氏數列 (Fibonacci Sequence)。 * **資料結構**:如二元樹的遍歷、快速排序 (Quick Sort)。 * **經典問題**:如河內塔 (Towers of Hanoi)、平面分割問題。 ----- ## 五、 資料型態與抽象資料型態 (ADT) ### 1\. 資料型態 (Data Type) 資料型態是一組**物件集合**,以及定義在這些物件上的**操作集合**。 * **範例(整數型態)**: * **物件集合**:所有整數 (如 ..., -2, -1, 0, 1, 2, ...)。 * **操作集合**:加、減、乘、除、比較運算 (如 \>、\< 等)。 ### 2\. 抽象資料型態 (Abstract Data Type, ADT) ADT 是一種資料型態,它將**物件的規格 (Specification)** 及其**操作**,與其**具體表示 (Representation)** 及**操作實現 (Implementation)** **分離**。 * **ADT 的重點在於「做什麼」(What) 而非「如何做」(How)。** * **範例:堆疊 (Stack) ADT** * **規格**:定義元素的集合、LIFO(後進先出)特性、基本操作 (如 push, pop)。 * **實現**:底層可以選擇使用**陣列 (Array)** 或**鏈結串列 (Linked List)** 來實作堆疊。 ----- ## 六、 效能分析與測量 * **效能測量 (Performance Measurement)**: * **依賴機器**:在特定硬體和軟體環境下,實際測量程式的執行時間和資源消耗。 * **效能分析 (Performance Analysis)**: * **不依賴機器**:主要關注演算法的**空間複雜度**與**時間複雜度**。 ### 1\. 空間複雜度 (Space Complexity) 衡量演算法執行所需的記憶體空間。包含: * **程式碼空間**:儲存程式指令的空間。 * **變數空間**:儲存常數和變數所需的空間。 * **遞迴堆疊空間**:遞迴呼叫所需的堆疊空間。 ### 2\. 時間複雜度 (Time Complexity) 衡量演算法執行所需的**基本運算步驟數**(Step Count),用來估計執行時間。 * **步驟計算方法**:透過計算每條指令的**執行次數 (頻率)**,並累加所有指令的總步數。 ----- ## 七、 演算法的漸進符號 (Asymptotic Notations) ### $O$ 符號(大 O 符號, Big Oh Notation) * **定義**:表示函數的**漸進上界**。 若存在正的常數 $c$ 和 $n_0$,使得對於所有 $n \ge n_0$,皆有 $f(n) \le c \cdot g(n)$ 成立,則稱 $f(n) = O(g(n))$。 * **用途**:用來描述演算法在**最壞情況**下的執行時間。 * **範例**: * $2n + 3 = O(n)$,因為當 $n \ge 3$ 時,$2n + 3 \le 3n$(取 $c=3, n_0=3$)。 * $3n^2 + 2n + 3 = O(n^2)$,因為當 $n \ge 3$ 時,$3n^2 + 2n + 3 \le 4n^2$(取 $c=4, n_0=3$)。 ### 常見的時間複雜度與成長順序 | 符號表示 | 名稱 | 成長速度 (由慢到快) | | :--- | :--- | :--- | | $O(1)$ | 常數時間 (Constant Time) | 1. $O(1)$ (常數) | | $O(\log n)$ | 對數時間 (Logarithmic Time) | 2. $O(\log n)$ (對數) | | $O(n)$ | 線性時間 (Linear Time) | 3. $O(n)$ (線性) | | $O(n \log n)$ | 線性對數時間 | 4. $O(n \log n)$ | | $O(n^2)$ | 平方時間 (Quadratic Time) | 5. $O(n^2)$ (平方) | | $O(n^3)$ | 立方時間 (Cubic Time) | 6. $O(n^3)$ (立方) | | $O(2^n)$ | 指數時間 (Exponential Time) | 7. $O(2^n)$ (指數) | | $O(n!)$ | 階乘時間 (Factorial Time) | 8. $O(n!)$ (階乘) | ----- ## 八、 排序演算法簡介 ### 1\. 堆疊排序 (Heap Sort) * **核心概念**:利用堆積樹 (Heap) 的特性。每次將目前最大(或最小)的元素移到正確的位置,然後將堆積的大小減 1,重複此過程。 ### 2\. 快速排序 (Quick Sort) * **核心概念**:採用**分治法 (Divide and Conquer)**。選擇一個元素作為**基準點 (Pivot)**,將所有小於基準點的元素移到左邊,大於基準點的元素移到右邊,然後對左右兩側子序列遞迴地進行排序。 ----- ## 九、 遞迴範例:河內塔 (Towers of Hanoi) * **遞迴函式**: ``` Hanoi(N, A, B, C): if N > 0: // 1. 將 N-1 個盤子從 A 移到 B (輔助柱) Hanoi(N-1, A, C, B) // 2. 將第 N 個盤子從 A 移到 C (目標柱) Move_Disk(A, C) // 3. 將 N-1 個盤子從 B 移到 C (目標柱) Hanoi(N-1, B, A, C) ``` * **步驟數 (時間複雜度)**: * 河內塔問題所需的總移動步數為 $2^N - 1$。 * 其時間複雜度為 $O(2^N)$。 ----- ## 堆疊 (Stack) 的 Python 實作 (使用列表 List) ```python # 初始化一個空棧 (Python 列表作為底層結構) stack = [] # Push 函式:將元素推入棧頂 (使用 list 的 append 方法) def Push(s, element): s.append(element) print(f"Pushed {element} to stack") # Pop 函式:從棧頂彈出元素 (使用 list 的 pop 方法) def Pop(s): # 檢查是否為空棧 (Underflow) if not s: # 相當於 len(s) == 0 print("Stack is empty (Underflow)") return None else: element = s.pop() print(f"Popped {element} from stack") return element # 範例 # Push(stack, 10) # Pop(stack) # Pop(stack) ```