🔀 合併排序法完整教學

程式碼、原理與運作演示

← 回到排序法選單

📌 基本概念

合併排序法(Merge Sort)是一種有效率的分治法排序演算法。其基本思想是:將序列不斷對半分割,直到每個子序列只剩一個元素,再將這些子序列兩兩合併成有序序列,最終合併成完整的排序結果。

合併排序法的時間複雜度為 O(n log n),無論最佳、最壞或平均情況皆如此,且屬於穩定排序。缺點是需要額外的記憶體空間。

⚙️ 操作原理與動畫演示

輸入數列,點擊「開始排序動畫」即可觀察合併排序的每一步。
(可自訂數列,逗號分隔)

⚙️ 詳細運作原理

演算法步驟:

1 分割: 將序列從中間分成兩半。
2 遞迴排序: 對左右兩半分別遞迴進行合併排序。
3 合併: 將兩個已排序的子序列合併成一個有序序列。

虛擬程式碼:

function mergeSort(arr): if len(arr) <= 1: return arr mid = len(arr) // 2 left = mergeSort(arr[:mid]) right = mergeSort(arr[mid:]) return merge(left, right) function merge(left, right): result = [] while left and right: if left[0] <= right[0]: result.append(left.pop(0)) else: result.append(right.pop(0)) result += left or right return result

📊 具體例子 - 排序 [5, 2, 8, 1, 9]

初始陣列: [5, 2, 8, 1, 9]
分割為 [5, 2] 和 [8, 1, 9]
[5, 2] → 分割為 [5]、[2] → 合併為 [2, 5]
[8, 1, 9] → 分割為 [8]、[1, 9] → [1, 9] 分割為 [1]、[9] → 合併為 [1, 9] → [8] 與 [1, 9] 合併為 [1, 8, 9]
最後 [2, 5] 與 [1, 8, 9] 合併為 [1, 2, 5, 8, 9]

💻 C語言完整程式碼

#include <stdio.h> // 合併兩個子陣列 void merge(int arr[], int l, int m, int r) { int n1 = m - l + 1; int n2 = r - m; int L[n1], R[n2]; for (int i = 0; i < n1; i++) L[i] = arr[l + i]; for (int j = 0; j < n2; j++) R[j] = arr[m + 1 + j]; int i = 0, j = 0, k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } // 合併排序主函數 void mergeSort(int arr[], int l, int r) { if (l < r) { int m = l + (r - l) / 2; mergeSort(arr, l, m); mergeSort(arr, m + 1, r); merge(arr, l, m, r); } } int main() { int numbers[] = {5, 2, 8, 1, 9}; int n = sizeof(numbers)/sizeof(numbers[0]); printf("原始數列: "); for (int i = 0; i < n; i++) { printf("%d ", numbers[i]); } printf("\n\n"); mergeSort(numbers, 0, n-1); printf("排序後的數列: "); for (int i = 0; i < n; i++) { printf("%d ", numbers[i]); } printf("\n"); return 0; }

⏳ 時間與空間複雜度

最佳/平均/最壞時間複雜度O(n log n)
空間複雜度O(n)
排序穩定性穩定
優點:
  • 適合大量資料排序,效率高
  • 排序結果穩定
  • 時間複雜度穩定
缺點:
  • 需要額外記憶體空間
  • 對小型資料集效率不如插入排序
← 回到排序法選單