冒泡排序看似簡單,實則暗藏邊界條件、比較方向、交換邏輯三大陷阱。本文針對典型錯誤代碼逐行解析,給出正確的降序/升序實現模板。
void bubblesort(intArr* ia) {
int i, j, t, n = ia->cur;
for (i = n; i > 2; i--) // 錯誤1:外層邊界
for (j = 1; j // 錯誤2:內層邊界缺失、缺少大括號
if (ia->pt[j] > ia->pt[j-1]) { // 錯誤3:> 為降序,註釋稱升序
t = ia->pt[j-1];
ia->pt[j-1] = ia->pt[j];
ia->pt[j] = t;
}
}
i > 2 應為 i > 1 (或 i >= 1),否則最後兩個元素不參與比較j 後無條件,應為 j < i (0 基址) 或 j <= i (1 基址)> 將大值前移實現降序,註釋卻寫升序
void bubbleSortAsc(int* arr, int n) {
for (int i = n - 1; i > 0; --i) { // 趟數:n-1 趟
bool swapped = false; // 優化:提前終止旗標
for (int j = 0; j < i; ++j) { // 每趟比較 0 到 i-1
if (arr[j] > arr[j + 1]) { // 相鄰逆序則交換
int t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
swapped = true;
}
}
if (!swapped) break; // 本趟無交換,已有序
}
}
void bubbleSortDesc(int* arr, int n) {
for (int i = n - 1; i > 0; --i) {
bool swapped = false;
for (int j = 0; j < i; ++j) {
if (arr[j] < arr[j + 1]) { // 改為 < 即降序
int t = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = t;
swapped = true;
}
}
if (!swapped) break;
}
}
typedef struct {
int* pt; // 數據指針
int cur; // 當前長度
} IntArr;
void bubbleSortIntArr(IntArr* ia, bool ascending) {
for (int i = ia->cur - 1; i > 0; --i) {
bool swapped = false;
for (int j = 0; j < i; ++j) {
bool needSwap = ascending ?
(ia->pt[j] > ia->pt[j + 1]) :
(ia->pt[j] < ia->pt[j + 1]);
if (needSwap) {
int t = ia->pt[j];
ia->pt[j] = ia->pt[j + 1];
ia->pt[j + 1] = t;
swapped = true;
}
}
if (!swapped) break;
}
}
| 版本 | 最好情況 | 最壞情況 | 平均情況 | 空間 | 穩定性 |
|---|---|---|---|---|---|
| 基本冒泡 | O(n²) | O(n²) | O(n²) | O(1) | 穩定 |
| 帶旗標優化 | O(n) | O(n²) | O(n²) | O(1) | 穩定 |
| 雞尾酒排序 | O(n) | O(n²) | O(n²) | O(1) | 穩定 |
核心口訣:外層控制趟數 (n-1),內層控制比較範圍 (遞減),相鄰比較逆序交換,旗標優化提前退出。掌握此模板,排序不再出錯。