📚 由淺至深
第 06 章 中等 約 18 分鐘

合併排序:分一半、各自排、再合起來

你跟同學分工排牌——一人排一半,最後合起來。這就是 Merge Sort,O(n log n)。

建議先看過: 05-selection-sort

想像你跟同學分工

[8, 3, 5, 1, 7, 2, 6, 4]↓ 切一半[8, 3, 5, 1][7, 2, 6, 4]↓ 再切(各自玩同樣的遊戲)[3, 8][1, 5][2, 7][4, 6]↑ 合併(兩兩合成排好的)[1, 3, 5, 8][2, 4, 6, 7]↑ 最後合併[1, 2, 3, 4, 5, 6, 7, 8] ✓

桌上有 100 張牌要排。一個人排太累—— 找個同學分一半,你排 50 張、他排 50 張,最後把兩疊合在一起

如果還是太多怎麼辦?繼續分! 50 → 25 → 12 → 6 → 3 → 2 → 1

切到一張時就不用排了(一張一定是「排好的」)。 然後從最小份開始兩兩合併

這就是「分治法 (Divide and Conquer)」的精神。

看一個完整的例子

[5, 3, 8, 1, 4, 7, 2, 6]

切階段(一直對半切到剩一個):

[5, 3, 8, 1, 4, 7, 2, 6]
        |
   [5,3,8,1]      [4,7,2,6]
     |                |
  [5,3]  [8,1]    [4,7]  [2,6]
   |  |   |  |     |  |   |  |
  [5][3] [8][1]   [4][7] [2][6]

合階段(兩兩合併成排好的):

  [5][3] → [3,5]   [8][1] → [1,8]   [4][7] → [4,7]   [2][6] → [2,6]
       \      /              \      /
       [1,3,5,8]              [2,4,6,7]
              \              /
              [1,2,3,4,5,6,7,8] ✓

合併兩個排好的陣列(核心動作)

這是 Merge Sort 最重要的子問題: 已知 L 和 R 都排好了,怎麼把它們合成一個排好的陣列?

想成兩疊牌都正面朝上: 比較兩疊的最上面那張,小的拿出來放到結果裡,重複直到拿完。

例:L = [1, 3, 5, 8]、R = [2, 4, 6, 7]

步驟L 剩R 剩結果
比 1 vs 2,拿 1[3,5,8][2,4,6,7][1]
比 3 vs 2,拿 2[3,5,8][4,6,7][1,2]
比 3 vs 4,拿 3[5,8][4,6,7][1,2,3]
比 5 vs 4,拿 4[5,8][6,7][1,2,3,4]
比 5 vs 6,拿 5[8][6,7][1,2,3,4,5]
比 8 vs 6,拿 6[8][7][1,2,3,4,5,6]
比 8 vs 7,拿 7[8][][1,2,3,4,5,6,7]
R 空了,倒出 L[][][1,2,3,4,5,6,7,8]
💡關鍵直覺

合併 n 個元素 → 每張牌看一次 → O(n)。 切割了 log n 次 → 總共 O(n log n)

Pseudocode

Algorithm MergeSort(A, left, right):
if left ≥ right: return // 只剩一個,停
mid ← (left + right) / 2
MergeSort(A, left, mid) // 排左半
MergeSort(A, mid+1, right) // 排右半
Merge(A, left, mid, right) // 合起來

複雜度

情境Big-O
最壞O(n log n)
平均O(n log n)
最好O(n log n)
空間O(n) — 需要額外陣列存合併結果
⚠️跟 O(n²) 比有多誇張

n = 1,000,000 時:

  • O(n²) 跑 1 兆次 → 慢到天荒地老
  • O(n log n) 跑 2 千萬次 → 不到 1 秒

這就是為什麼真實世界的排序庫都用 O(n log n) 等級的演算法。

📝考試會這樣考

題型一:畫遞迴樹。 給陣列,要你畫出 Merge Sort 的「切割樹」和「合併樹」。 訣竅:對半切到剩一個,再倒著合回去。每一層寫清楚分到的子陣列。

題型二:算複雜度(這是經典)。

遞迴關係式:T(n)=2T(n/2)+O(n)T(n) = 2T(n/2) + O(n)

用 Master Theorem 解出 T(n) = O(n log n)

怎麼直觀理解

  • 切割了 log n 層
  • 每層合併總共要花 O(n)
  • 所以總共 層數 × 每層成本 = log n × n = O(n log n)

題型三:為什麼 Merge Sort 是 stable(穩定)? 合併時如果 L 和 R 的最上面相等,先拿 L 的——這樣相同值的相對順序不變。

這章記住

  1. 分一半 → 各自排 → 合起來,這個套路叫分治 (Divide and Conquer)
  2. 合併兩個排好陣列只需 O(n),總共 O(n log n)
  3. 缺點:需要額外的空間 O(n)

學習進度只存在你的瀏覽器,不會上傳。