---
# System prepended metadata

title: 資料結構 第一章
tags: [Data Structure]

---


## 二、 程式的創建流程（瀑布模型）

程式開發通常遵循以下步驟：

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) 
```