排序演算法是資料結構與演算法的基石。本文提供三種經典 O(n²) 排序——氣泡排序、插入排序、選擇排序的完整 Java 實作、步驟圖解、效能分析與優化技巧,並附上可直接執行的程式碼範例。
重複掃描序列,比較相鄰元素,逆序則交換。每輪將最大元素「氣泡」至末端。優化:若某輪無交換,提前結束 (已有序)。
public class BubbleSortDemo {
// 優化版:雙向掃描 + 提前結束旗標
public void bubbleSort(int[] numlist) {
int temp;
boolean swapped;
// 外層:未排序區間縮減 [0, out]
for (int out = numlist.length - 1; out > 0; out--) {
swapped = true;
// 內層:正向掃描將大值推後
for (int in = 0; in < out; in++) {
if (numlist[in] > numlist[in + 1]) {
temp = numlist[in];
numlist[in] = numlist[in + 1];
numlist[in + 1] = temp;
swapped = false;
}
}
if (swapped) break; // 本輪無交換,已有序
printArray(numlist); // 觀察每輪結果
}
}
public void printArray(int[] arr) {
for (int v : arr) System.out.print(v + " ");
System.out.println();
}
public static void main(String[] args) {
BubbleSortDemo demo = new BubbleSortDemo();
int[] num = {4, 11, 17, 6, 1, 2, 13, 15};
System.out.println("原序列:"); demo.printArray(num);
System.out.println("每輪氣泡排序後:"); demo.bubbleSort(num);
}
}
將陣列分為「已排序區」與「未排序區」。每次從未排序區取首元素,在已排序區中從右向左比較位移,找到插入點。類似整理撲克牌。
public class InsertSortDemo {
public void insertSort(int[] numlist) {
int temp;
// 外層:out 為未排序區首元素索引
for (int out = 1; out < numlist.length; out++) {
temp = numlist[out]; // 待插入值
int in = out;
// 內層:已排序區從右向左掃描,大於 temp 者右移
while (in > 0 && temp < numlist[in - 1]) {
numlist[in] = numlist[in - 1]; // 右移
in--;
}
numlist[in] = temp; // 插入空位
}
}
// printArray/main 同前
}
每輪在未排序區尋找最小元素,與區首元素交換。不需相鄰比較交換,僅每輪 1 次交換。
public class SelectSortDemo {
public void selectSort(int[] numlist) {
int temp;
for (int out = 0; out < numlist.length; out++) {
int min = out; // 假設 out 為最小
// 掃描未排序區尋找真正最小值索引
for (int in = out + 1; in < numlist.length; in++) {
if (numlist[in] < numlist[min]) min = in;
}
// 單次交換將最小值放至 out 位置
temp = numlist[out];
numlist[out] = numlist[min];
numlist[min] = temp;
}
}
// printArray/main 同前
}
| 維度 | 氣泡排序 | 插入排序 | 選擇排序 |
|---|---|---|---|
| 平均時間 | O(n²) | O(n²) | O(n²) |
| 最好時間 | O(n) | O(n) | O(n²) |
| 資料移動 | 頻繁交換 | 位移為主 | 最少 (n 次交換) |
| 穩定性 | 穩定 | 穩定 | 不穩定 |
| 適用場景 | 教學、極小資料 | 小資料、近乎有序、混合排序基礎 | 寫入昂貴、記憶體受限 |
實務開發請直接使用 Arrays.sort() (雙軸快速排序,基本型別) 或 Collections.sort() / List.sort() (TimSort,物件參考),時間複雜度 O(n log n)、高度優化、穩定。僅在教學、嵌入式無標準庫、或特殊約束 (如寫入極昂貴) 時手寫 O(n²) 排序。
// 實務標準用法
int[] arr = {4, 11, 17, 6, 1, 2, 13, 15};
Arrays.sort(arr); // 原地排序,最快
System.out.println(Arrays.toString(arr)); // [1, 2, 4, 6, 11, 13, 15, 17]
Arrays/Collections.sort。