📊 資料結構總複習

快速回顧所有重要的資料結構概念

1️⃣ 為什麼要學習資料結構?

資料結構是程式的基石,選擇正確的資料結構可以讓程式更高效、更簡潔。

2️⃣ 陣列(Array)

基本概念

陣列是最基本的資料結構,元素在記憶體中連續排列。

操作時間複雜度
隨機存取O(1)
搜尋O(n)
插入(末端)O(1)
刪除(末端)O(1)
插入/刪除(中間)O(n)

優點

缺點

Python 範例

# 建立陣列
arr = [1, 2, 3, 4, 5]

# 隨機存取 O(1)
print(arr[2])  # 輸出: 3

# 遍歷
for num in arr:
    print(num)

# 列表推導式
squares = [x**2 for x in range(10)]

3️⃣ 連結串列(Linked List)

基本概念

每個節點包含資料和指向下一個節點的指標。

操作時間複雜度
隨機存取O(n)
頭部插入O(1)
頭部刪除O(1)
尾端插入O(n)*

* 如果有尾指針則為 O(1)

單向串列實作

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class LinkedList:
    def __init__(self):
        self.head = None
    
    def append(self, val):
        new_node = ListNode(val)
        if not self.head:
            self.head = new_node
            return
        current = self.head
        while current.next:
            current = current.next
        current.next = new_node
    
    def prepend(self, val):
        new_node = ListNode(val, self.head)
        self.head = new_node
    
    def delete(self, val):
        if not self.head:
            return
        if self.head.val == val:
            self.head = self.head.next
            return
        current = self.head
        while current.next:
            if current.next.val == val:
                current.next = current.next.next
                return
            current = current.next
💡 提示:串列適合頻繁的頭部操作,不需要移動元素。

4️⃣ 堆疊(Stack)

基本概念

後進先出(LIFO, Last In First Out)的資料結構。

操作時間複雜度
push(推入)O(1)
pop(彈出)O(1)
peek(查看頂端)O(1)
isEmptyO(1)

應用場景

Python 實作

# 使用列表實現堆疊
stack = []

# push
stack.append(10)
stack.append(20)
stack.append(30)

# pop
top = stack.pop()  # top = 30
print(top)

# 查看頂端
print(stack[-1])  # 20

# 判斷空
if not stack:
    print("堆疊為空")
✅ 經典題目:Valid Parentheses、Daily Temperatures、Evaluate Reverse Polish Notation

5️⃣ 佇列(Queue)

基本概念

先進先出(FIFO, First In First Out)的資料結構。

操作時間複雜度
enqueue(入隊)O(1)
dequeue(出隊)O(1)
frontO(1)
isEmptyO(1)

Python 實作(使用 collections.deque)

from collections import deque

queue = deque()

# enqueue
queue.append(10)
queue.append(20)
queue.append(30)

# dequeue
front = queue.popleft()  # front = 10

# 查看前端
print(queue[0])  # 20

# 判斷空
if not queue:
    print("佇列為空")

雙端佇列(Deque)

兩端都可以進行插入和刪除:

# 雙端操作
queue.appendleft(5)   # 在前端插入
queue.append(40)      # 在尾端插入
queue.popleft()       # 從前端刪除
queue.pop()           # 從尾端刪除
✅ 應用:廣度優先搜尋(BFS)、任務排程、快取(LRU Cache)

6️⃣ 雜湊表(Hash Table)

基本概念

透過雜湊函數將鍵映射到值的資料結構。

操作平均時間最差時間
搜尋O(1)O(n)
插入O(1)O(n)
刪除O(1)O(n)

Python 實作

# 使用字典
hash_table = {}

# 插入
hash_table["name"] = "Anzu"
hash_table["age"] = 25
hash_table["role"] = "AI Assistant"

# 搜尋
print(hash_table.get("name"))  # "Anzu"
print(hash_table.get("unknown", "default"))  # "default"

# 遍歷
for key, value in hash_table.items():
    print(f"{key}: {value}")

碰撞處理

⚠️ 注意:避免所有鍵產生相同的雜湊值(Hash Collision)

7️⃣ 樹(Tree)

基本概念

由節點組成的層級資料結構,有一個根節點。

常用術語

二元樹遍歷

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

# 前序遍歷(根 -> 左 -> 右)
def preorder(root):
    if not root:
        return
    print(root.val)
    preorder(root.left)
    preorder(root.right)

# 中序遍歷(左 -> 根 -> 右)
def inorder(root):
    if not root:
        return
    inorder(root.left)
    print(root.val)
    inorder(root.right)

# 後序遍歷(左 -> 右 -> 根)
def postorder(root):
    if not root:
        return
    postorder(root.left)
    postorder(root.right)
    print(root.val)

8️⃣ 圖(Graph)

基本概念

由節點(頂點)和邊組成的資料結構。

圖的類型

圖的表示

# 鄰接表(Adjacency List)
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}

# 鄰接矩陣(Adjacency Matrix)
#    A  B  C  D  E  F
# A [0, 1, 1, 0, 0, 0]
# B [1, 0, 0, 1, 1, 0]
# ...

圖的遍歷

# BFS(廣度優先搜尋)
from collections import deque

def bfs(graph, start):
    visited = set([start])
    queue = deque([start])
    while queue:
        node = queue.popleft()
        print(node)
        for neighbor in graph[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append(neighbor)

# DFS(深度優先搜尋)
def dfs(graph, node, visited=None):
    if visited is None:
        visited = set()
    visited.add(node)
    print(node)
    for neighbor in graph[node]:
        if neighbor not in visited:
            dfs(graph, neighbor, visited)
✅ 應用:社群網路、推薦系統、路徑規劃、網頁爬蟲

📊 資料結構比較總表

資料結構搜尋插入刪除空間
ArrayO(1)O(n)O(n)O(n)
Linked ListO(n)O(1)*O(1)*O(n)
StackO(n)O(1)O(1)O(n)
QueueO(n)O(1)O(1)O(n)
Hash TableO(1)**O(1)**O(1)**O(n)
Binary TreeO(log n)***O(log n)***O(log n)***O(n)
GraphO(V+E)O(1)O(1)O(V+E)

* 頭部操作 | ** 平均情況 | *** 平衡樹

📝 自我測驗

Q1: 什麼情況下使用堆疊比使用佇列更合適?

Ans: 當需要「後進先出」的順序時,如函數呼叫堆疊、括號匹配、DFS。

Q2: 陣列和連結串列的主要差異是什麼?

Ans: 陣列記憶體連續,可隨機存取 O(1);串列記憶體不連續,插入刪除 O(1)。

Q3: 為什麼雜湊表需要處理碰撞?

Ans: 不同鍵可能雜湊到同一位置,碰撞會導致資料丟失或錯誤。

Q4: BFS 和 DFS 分別適合什麼場景?

Ans: BFS 適合找最短路徑、分層遍歷;DFS 適合遍歷所有路徑、檢查是否存在。

✅ 完成學習

完成本教材後,點擊下方按鈕記錄你的學習進度!