相鄰元素兩兩比較,逆序則交換。每輪將最大/最小元素「冒泡」到端點。穩定排序,時間 O(n²)。
void bubble1(int a[], int n) { // 正向
for (int i = 1; i < n; i++)
for (int j = 0; j < n - i; j++)
if (a[j] > a[j+1]) swap(a[j], a[j+1]);
}
void bubble1r(int a[], int n) { // 反向
for (int i = 1; i < n; i++)
for (int j = n-1; j >= i; j--)
if (a[j-1] > a[j]) swap(a[j-1], a[j]);
}
若某輪無交換,說明已有序,直接跳出。
void bubble2(int a[], int n) {
bool swapped = true;
for (int i = 1; i < n && swapped; i++) {
swapped = false;
for (int j = 0; j < n - i; j++)
if (a[j] > a[j+1]) { swap(a[j], a[j+1]); swapped = true; }
}
}
最後一次交換位置 k 之後的元素已有序,下輪只需掃描到 k。
void bubble3(int a[], int n) {
int bound = n - 1;
while (bound > 0) {
int lastSwap = 0;
for (int j = 0; j < bound; j++)
if (a[j] > a[j+1]) { swap(a[j], a[j+1]); lastSwap = j; }
if (lastSwap == 0) break; // 本輪無交換
bound = lastSwap;
}
}
void swap(int& a, int& b) {
if (a != b) { a ^= b; b ^= a; a ^= b; }
}
| 版本 | 最好情況 | 最壞情況 | 平均 | 備註 |
|---|---|---|---|---|
| 基礎 | O(n²) | O(n²) | O(n²) | 無優化 |
| 標記 | O(n) | O(n²) | O(n²) | 近乎有序極快 |
| 邊界 | O(n) | O(n²) | O(n²) | 部分有序顯著加速 |
int main() {
vector a = {64, 34, 25, 12, 22, 11, 90};
bubble3(a.data(), a.size());
for (int x : a) cout << x << ' ';
return 0;
}
冒泡排序雖非工程首選(std::sort 更快),但其三級優化思路——標記提前退出、記錄邊界縮小範圍——體現了「利用問題特性減少無效比較」的算法設計智慧。理解這三個版本,有助於掌握插入排序、快速排序等更高級算法的優化靈感來源。