冒泡排序通過重複遍歷數組,比較相鄰元素並交換逆序對,將最大元素像氣泡一樣「浮」到末尾。每輪遍歷確定一個元素的最終位置。
void bubbleSort(vector& a) {
int n = a.size();
for (int i = 0; i < n-1; ++i) {
bool swapped = false;
for (int j = 0; j < n-1-i; ++j) {
if (a[j] > a[j+1]) {
swap(a[j], a[j+1]);
swapped = true;
}
}
if (!swapped) break; // 提前終止優化
}
}
swapped 標記:若某輪無交換,說明已有序,提前退出。奇數輪正向冒泡(大元素右移),偶數輪反向冒泡(小元素左移)。同時縮減左右邊界。
void cocktailSort(vector& a) {
int n = a.size();
int left = 0, right = n - 1;
while (left < right) {
bool swapped = false;
// 正向:大元素右移
for (int i = left; i < right; ++i)
if (a[i] > a[i+1]) { swap(a[i], a[i+1]); swapped = true; }
if (!swapped) break;
--right; // 最大元素已就位
// 反向:小元素左移
swapped = false;
for (int i = right; i > left; --i)
if (a[i-1] > a[i]) { swap(a[i-1], a[i]); swapped = true; }
if (!swapped) break;
++left; // 最小元素已就位
}
}
| 版本 | 耗時 (ms) | 比較次數 | 交換次數 |
|---|---|---|---|
| 標準冒泡 | ~45 | ~2,000,000 | ~500,000 |
| 雙向冒泡 | ~30 | ~1,800,000 | ~500,000 |
| std::sort | ~1 | ~22,000 | ~7,000 |
雙向冒泡約快 30%,但仍屬 $O(n^2)$,僅適合教學或極小數據量($n \le 50$)。
| 情況 | 時間複雜度 | 比較次數 | 交換次數 |
|---|---|---|---|
| 最好(已有序) | $O(n)$ | $n-1$ | 0 |
| 最壞(逆序) | $O(n^2)$ | $n(n-1)/2$ | $n(n-1)/2$ |
| 平均 | $O(n^2)$ | $n(n-1)/4$ | $n(n-1)/4$ |
空間複雜度 $O(1)$,穩定排序。
std::sort(IntroSort:快速+堆+插入混合,$O(n \log n)$ 保證)。std::sort 內部也會切換到插入排序。
#include
using namespace std;
void bubbleSort(vector& a) { /* 版本一 */ }
void cocktailSort(vector& a) { /* 版本二 */ }
int main() {
vector a = {64, 34, 25, 12, 22, 11, 90};
bubbleSort(a);
for (int x : a) cout << x << ' '; // 11 12 22 25 34 64 90
cout << '\n';
vector b = {64, 34, 25, 12, 22, 11, 90};
cocktailSort(b);
for (int x : b) cout << x << ' '; // 11 12 22 25 34 64 90
return 0;
}