每一輪從未排序區間選出最小(或最大)元素,與未排序區間首位元素交換。共進行 n-1 輪。
初始:[64, 25, 12, 22, 11]
第1輪:選出 11 ↔ 交換 64 → [11, 25, 12, 22, 64]
第2輪:選出 12 ↔ 交換 25 → [11, 12, 25, 22, 64]
第3輪:選出 22 ↔ 交換 25 → [11, 12, 22, 25, 64]
第4輪:選出 25 ↔ 交換 25 → [11, 12, 22, 25, 64](已有序)
public static void selectionSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIdx = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIdx]) minIdx = j;
}
if (minIdx != i) {
int tmp = arr[i];
arr[i] = arr[minIdx];
arr[minIdx] = tmp;
}
}
}
O(n²)(雙重循環固定)。O(1) 原地排序。相鄰元素兩兩比較,大的「冒泡」到右端。每輪將當前最大元素固定到未排序區間末尾。可加入有序標記提前終止。
初始:[64, 25, 12, 22, 11]
第1輪:64↔25, 64↔12, 64↔22, 64↔11 → [25, 12, 22, 11, 64]
第2輪:25↔12, 25↔22, 25↔11 → [12, 22, 11, 25, 64]
第3輪:22↔11 → [12, 11, 22, 25, 64]
第4輪:12↔11 → [11, 12, 22, 25, 64]
public static void bubbleSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
boolean swapped = false;
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
swapped = true;
}
}
if (!swapped) break; // 本輪無交換,說明已有序
}
}
O(n²),最好 O(n)(已有序時)。O(1)。O(n²)。| 維度 | 選擇排序 | 冒泡排序 |
|---|---|---|
| 核心操作 | 選最小 + 換位 | 相鄰比較 + 交換 |
| 最好時間 | O(n²) | O(n) (優化版) |
| 最壞時間 | O(n²) | O(n²) |
| 穩定性 | 不穩定 | 穩定 |
| 交換次數 | ≤ n-1 (極少) | O(n²) (較多) |
| 適用場景 | 數據量小、寫入昂貴、不要求穩定 | 教學、近乎有序數據、需穩定排序 |
O(n) 降為 O(log n),整體 O(n log 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²) O(log n) ✗
堆排序 O(n log n) O(n log n) O(1) ✗
歸並排序 O(n log n) O(n log n) O(n) ✓
希爾排序 O(n^1.3) O(n²) O(1) ✗
基數排序 O(nk) O(nk) O(n+k) ✓
Arrays.sort()(雙軸快排/歸並混合)或 Collections.sort()(TimSort),穩定且高性能。理解基礎排序的原理與優缺點,是掌握高級算法、優化系統性能的基石。