選擇排序:每輪從未排序區間選出最小(大)元素,與未排序區間首位元素交換。時間複雜度 O(n²),空間 O(1),不穩定。
初始: [64, 25, 12, 22, 11] 第1輪: 選最小 11 ↓ 交換 64 → [11, 25, 12, 22, 64] 第2輪: 選最小 12 ↓ 交換 25 → [11, 12, 25, 22, 64] 第3輪: 選最小 22 ↓ 交換 25 → [11, 12, 22, 25, 64] 第4輪: 選最小 25 ↓ 交換 25 → [11, 12, 22, 25, 64] (已有序) 完成: [11, 12, 22, 25, 64]
public class SelectionSort {
// 升序
public static void sort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
int minIdx = i;
// 內層循環:在 [i+1, n-1] 找最小值索引
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIdx]) minIdx = j;
}
// 交換 (若 minIdx != i)
if (minIdx != i) {
int tmp = arr[i];
arr[i] = arr[minIdx];
arr[minIdx] = tmp;
}
}
}
// 降序 (只需改比較方向)
public static void sortDesc(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int maxIdx = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] > arr[maxIdx]) maxIdx = j;
}
if (maxIdx != i) swap(arr, i, maxIdx);
}
}
private static void swap(int[] a, int i, int j) {
int t = a[i]; a[i] = a[j]; a[j] = t;
}
// 泛型版 (支援 Comparable)
public static > void sort(T[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIdx = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j].compareTo(arr[minIdx]) < 0) minIdx = j;
}
if (minIdx != i) swap(arr, i, minIdx);
}
}
private static void swap(T[] a, int i, int j) {
T t = a[i]; a[i] = a[j]; a[j] = t;
}
}
| 指標 | 數值 | 說明 |
|---|---|---|
| 時間複雜度 (最好/平均/最壞) | O(n²) / O(n²) / O(n²) | 與輸入無關,永遠雙層循環 |
| 空間複雜度 | O(1) | 原地排序,僅常數額外空間 |
| 穩定性 | 不穩定 | 交換可能改變相等元素相對順序 |
| 交換次數 | 0 ~ n-1 | 最少交換排序算法之一 |
// Java 內建排序 (雙軸快排 + 歸併 + 插入排序混合)
Arrays.sort(arr); // 基本類型:Dual-Pivot Quicksort
Arrays.sort(objArr); // 物件:TimSort (歸併+插入),穩定、O(n log n)
Collections.sort(list); // 同 Arrays.sort
JDK 排序在實際數據分佈下表現遠超 O(n²) 算法,且經過極致優化 (內部函數、分支預測、緩存友好)。