冒泡排序通過重複遍歷數組,比較相鄰元素並交換順序,將較大元素像氣泡一樣逐步「浮」到數組末端。每輪遍歷確定一個最大值位置。
初始: [5, 2, 9, 1, 5, 6]
第1輪: [2, 5, 1, 5, 6, 9] ← 9 沉底
第2輪: [2, 1, 5, 5, 6, 9] ← 6 就位
第3輪: [1, 2, 5, 5, 6, 9] ← 5 就位
第4輪: [1, 2, 5, 5, 6, 9] ← 已有序,提前終止
第5輪: [1, 2, 5, 5, 6, 9] ← 完成
public class BubbleSort {
/**
* 基礎版冒泡排序
* @param arr 待排序數組
* @param 泛型類型,需實現 Comparable
*/
public static > void bubbleSort(T[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
// 每輪將最大值冒泡到 n-1-i 位置
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j].compareTo(arr[j + 1]) > 0) {
swap(arr, j, j + 1);
}
}
}
}
/**
* 優化版:增加有序標記,提前終止
*/
public static > void bubbleSortOptimized(T[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
boolean swapped = false;
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j].compareTo(arr[j + 1]) > 0) {
swap(arr, j, j + 1);
swapped = true;
}
}
if (!swapped) break; // 本輪無交換,說明已有序
}
}
/**
* 進階優化:記錄最後交換位置,縮小下輪範圍
*/
public static > void bubbleSortAdvanced(T[] arr) {
int n = arr.length;
int lastSwap = n - 1;
while (lastSwap > 0) {
int currentSwap = 0;
for (int j = 0; j < lastSwap; j++) {
if (arr[j].compareTo(arr[j + 1]) > 0) {
swap(arr, j, j + 1);
currentSwap = j;
}
}
lastSwap = currentSwap;
}
}
private static void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
| 指標 | 基礎版 | 優化版 | 進階版 |
|---|---|---|---|
| 最好情況 | O(n²) | O(n) | O(n) |
| 平均情況 | O(n²) | O(n²) | O(n²) |
| 最壞情況 | O(n²) | O(n²) | O(n²) |
| 空間複雜度 | O(1) | O(1) | O(1) |
| 穩定性 | 穩定 | ||
基礎版: ~2.8 秒
優化版(有序): ~0.003 秒 (最好情況)
優化版(逆序): ~2.1 秒
進階版(逆序): ~1.6 秒
Arrays.sort: ~0.01 秒 (雙軸快排)
public static > void bubbleSortRecursive(T[] arr, int n) {
if (n == 1) return; // 基線條件
boolean swapped = false;
for (int i = 0; i < n - 1; i++) {
if (arr[i].compareTo(arr[i + 1]) > 0) {
swap(arr, i, i + 1);
swapped = true;
}
}
if (!swapped) return; // 優化:提前終止
bubbleSortRecursive(arr, n - 1); // 遞歸處理前 n-1 個元素
}
冒泡排序雖是入門級算法,但其優化思路(標記位、縮小邊界、遞歸轉換)體現了算法優化的通用思想:**發現規律、減少無效操作、利用問題特性**。理解這些優化,對學習快速排序、歸併排序等高級算法大有裨益。