重複遍歷陣列,比較相鄰元素,逆序則交換。每輪將最大元素「冒泡」至未排序區末端。
public class BubbleSort {
public static void sort(int[] arr) {
if (arr == null || arr.length <= 1) return;
for (int i = 0; i < arr.length - 1; i++) { // 趟數
for (int j = 0; j < arr.length - i - 1; j++) { // 未排序區比較
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
}
}
}
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
}
}
若某輪無任何交換,說明已有序。
public static void sortOptimized1(int[] arr) {
if (arr == null || arr.length <= 1) return;
boolean swapped;
for (int i = 0; i < arr.length - 1; i++) {
swapped = false;
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1);
swapped = true;
}
}
if (!swapped) break; // 已有序
}
}
最後交換位置之後的元素已有序,下輪只需掃描到該位置。
public static void sortOptimized2(int[] arr) {
if (arr == null || arr.length <= 1) return;
int n = arr.length;
while (n > 1) {
int newN = 0;
for (int j = 1; j < n; j++) {
if (arr[j - 1] > arr[j]) {
swap(arr, j - 1, j);
newN = j; // 記錄最後交換索引
}
}
n = newN; // 下輪邊界
}
}
正向冒泡最大值到右端,反向冒泡最小值到左端,減少來回移動。
public static void cocktailSort(int[] arr) {
if (arr == null || arr.length <= 1) return;
int left = 0, right = arr.length - 1;
while (left < right) {
// 正向
for (int i = left; i < right; i++) {
if (arr[i] > arr[i + 1]) swap(arr, i, i + 1);
}
right--;
// 反向
for (int i = right; i > left; i--) {
if (arr[i - 1] > arr[i]) swap(arr, i - 1, i);
}
left++;
}
}
| 版本 | 最佳 (已排序) | 平均 | 最差 (逆序) | 空間 | 穩定性 |
|---|---|---|---|---|---|
| 基礎版 | O(n²) | O(n²) | O(n²) | O(1) | 穩定 |
| 旗標優化 | O(n) | O(n²) | O(n²) | O(1) | 穩定 |
| 邊界記錄 | O(n) | O(n²) | O(n²) | O(1) | 穩定 |
| 雞尾酒 | O(n) | O(n²) | O(n²) | O(1) | 穩定 |
基礎版: ~120 ms 旗標優化: ~65 ms (隨機數據約 45% 比較被跳過) 邊界記錄: ~55 ms (進一步減少比較次數) 雞尾酒: ~50 ms Arrays.sort(): ~2 ms (雙軸快速排序) Collections.sort(): ~3 ms (TimSort)
// 基本類型陣列 (雙軸快速排序)
int[] arr = {5, 2, 8, 1, 9};
Arrays.sort(arr);
// 物件陣列/列表 (TimSort - 穩定、適應性強)
String[] strs = {"banana", "apple", "pear"};
Arrays.sort(strs); // 自然順序
Arrays.sort(strs, Comparator.comparingInt(String::length)); // 自定義
List<User> users = ...;
users.sort(Comparator.comparing(User::getAge).thenComparing(User::getName));
Collections.sort(users, (u1, u2) -> u1.getAge() - u2.getAge());
| 錯誤 | 表現 | 修正 |
|---|---|---|
外層迴圈條件 i < arr.length | 多執行一輪、索引越界風險 | i < arr.length - 1 |
內層迴圈條件 j < arr.length | j+1 越界 | j < arr.length - i - 1 |
| 交換邏輯寫錯 | 數值丟失 | 使用暫存變數或 arr[i] ^= arr[j]; arr[j] ^= arr[i]; arr[i] ^= arr[j]; (僅整數) |
| 未處理 null/空陣列 | NPE | 開頭加 if (arr == null || arr.length <= 1) return; |
public static <T extends Comparable<? super T>> void bubbleSort(T[] arr) {
if (arr == null || arr.length <= 1) return;
for (int i = 0; i < arr.length - 1; i++) {
boolean swapped = false;
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j].compareTo(arr[j + 1]) > 0) {
T tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp;
swapped = true;
}
}
if (!swapped) break;
}
}