| 類別 | 算法 | 平均時間複雜度 | 最壞情況 | 空間複雜度 | 穩定性 |
|---|---|---|---|---|---|
| 簡單排序 O(N²) | 冒泡排序 | O(N²) | O(N²) | O(1) | 穩定 |
| 交換排序 | O(N²) | O(N²) | O(1) | 不穩定 | |
| 選擇排序 | O(N²) | O(N²) | O(1) | 不穩定 | |
| 高級排序 O(N log N) | 快速排序 | O(N log N) | O(N²) | O(log N) | 不穩定 |
| 特殊/教學 | 希爾排序 | O(N^1.3~2) | O(N²) | O(1) | 不穩定 |
| 堆排序 | O(N log N) | O(N log N) | O(1) | 不穩定 |
核心思想:相鄰元素兩兩比較,大的「冒泡」到右端。每輪將當前最大值固定到末尾。
void BubbleSort(int* a, int n) {
for (int i = 1; i < n; i++) {
for (int j = n - 1; j >= i; j--) {
if (a[j] < a[j-1]) {
int tmp = a[j-1]; a[j-1] = a[j]; a[j] = tmp;
}
}
}
}
性能分析:
Σ(i=1 to n-1) (n-i) = n(n-1)/2 = O(N²)核心思想:第 i 輪,用 a[i] 與後續所有元素比較,發現更小即交換。最終 a[i] 為當前最小值。
void ExchangeSort(int* a, int n) {
for (int i = 0; i < n-1; i++) {
for (int j = i+1; j < n; j++) {
if (a[j] < a[i]) {
int tmp = a[i]; a[i] = a[j]; a[j] = tmp;
}
}
}
}
比較次數同冒泡 O(N²),交換次數略多(每次發現更小即交換),實際較慢。
核心思想:第 i 輪,掃描未排序區找到最小值索引 minIdx,**僅交換一次** a[i] 和 a[minIdx]。
void SelectionSort(int* a, int n) {
for (int i = 0; i < n-1; i++) {
int minIdx = i;
for (int j = i+1; j < n; j++)
if (a[j] < a[minIdx]) minIdx = j;
if (minIdx != i) {
int tmp = a[i]; a[i] = a[minIdx]; a[minIdx] = tmp;
}
}
}
優勢:交換次數固定 N-1(O(N)),適合**寫入成本高**(如 Flash、EEPROM)場景。
核心思想:分治法。選基準,分區使左側 ≤ 基準 ≤ 右側,遞歸排序子區。
void QuickSort(int* a, int left, int right) {
if (left >= right) return;
int pivot = a[(left + right) / 2];
int i = left, j = right;
while (i <= j) {
while (a[i] < pivot) i++;
while (a[j] > pivot) j--;
if (i <= j) { int tmp = a[i]; a[i++] = a[j]; a[j--] = tmp; }
}
if (left < j) QuickSort(a, left, j);
if (i < right) QuickSort(a, i, right);
}
關鍵優化:
插入排序改進:按增量分組插入,逐步縮小增量至 1。打破 O(N²) 下界,實際極快。
利用最大堆特性,每次取堆頂與末尾交換,再調整堆。保證 O(N log N) 最壞情況,原地排序。
| 場景 | 推薦算法 | 理由 |
|---|---|---|
| 數據量小 (N < 50) | 插入排序 / 選擇排序 | 常數小、無遞歸、代碼簡短 |
| 通用高性能排序 | 快速排序 (std::sort / qsort) | 平均最快、庫實現經過深度優化 |
| 要求穩定 / 最壞情況保證 | 歸併排序 / Timsort | O(N log N) 最壞情況、穩定 |
| 嵌入式/內存受限 | 堆排序 / 希爾排序 | O(1) 空間、無遞歸 |
| 近乎有序數據 | 插入排序 / Timsort | 最好 O(N) |
qsort 使用示例int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; }
qsort(arr, n, sizeof(int), cmp);
理解排序算法不僅是背誦代碼,更要掌握:**複雜度推導、穩定性、適應性、空間權衡、實際常數因子**。「簡單排序」用於教學與微小數據,「快速排序」是工程首選,「歸併/堆/希爾」解決特定約束。實際開發中**優先使用標準庫**,僅在極端約束下手寫優化。