| 類別 | 算法 | 平均時間 | 最壞時間 | 空間 | 穩定性 | 適用場景 |
|---|---|---|---|---|---|---|
| 插入類 | 直接插入 | O(n²) | O(n²) | O(1) | ✅ | 小規模、近乎有序 |
| 折半插入 | O(n²) | O(n²) | O(1) | ✅ | 比較次數減半 | |
| 希爾排序 | O(n^1.3) | O(n²) | O(1) | ❌ | 中等規模、不穩定可接受 | |
| 交換類 | 冒泡排序 | O(n²) | O(n²) | O(1) | ✅ | 教學、極小數據 |
| 快速排序 | O(n log n) | O(n²) | O(log n) | ❌ | 大規模通用首選 | |
| 選擇類 | 直接選擇 | O(n²) | O(n²) | O(1) | ❌ | 交換成本高於比較 |
| 堆排序 | O(n log n) | O(n log n) | O(1) | ❌ | 大規模、嚴格 O(n log n) | |
| 歸並類 | 歸並排序 | O(n log n) | O(n log n) | O(n) | ✅ | 外部排序、穩定要求、鏈表 |
| 基數類 | 基數排序 | O(d·n) | O(d·n) | O(n) | ✅ | 整數、字符串、固定長度鍵 |
選型口訣:
SortDemopackage com.test;
import java.util.Random;
public class SortDemo {
// ---------- 工具方法 ----------
public int[] createArray() {
Random r = new Random();
int[] a = new int[10];
for (int i = 0; i < 10; i++) a[i] = r.nextInt(100) - r.nextInt(100); // 含負數
printArray(a, "原始序列");
return a;
}
public void printArray(int[] a, String tag) {
System.out.print(tag + ":");
for (int v : a) System.out.print(v + " ");
System.out.println();
}
private void swap(int[] a, int i, int j) {
int t = a[i]; a[i] = a[j]; a[j] = t;
}
// ---------- 1. 冒泡排序 ----------
public void bubbleSort(int[] a, boolean asc) {
for (int i = 1; i < a.length; i++) {
boolean swapped = false;
for (int j = 0; j < a.length - i; j++) {
if (asc ? a[j] > a[j+1] : a[j] < a[j+1]) {
swap(a, j, j+1);
swapped = true;
}
}
if (!swapped) break; // 優化:提前終止
}
printArray(a, asc ? "冒泡↑" : "冒泡↓");
}
// ---------- 2. 直接選擇排序 ----------
public void selectSort(int[] a, boolean asc) {
for (int i = 0; i < a.length - 1; i++) {
int extIdx = i;
for (int j = i + 1; j < a.length; j++) {
if (asc ? a[j] < a[extIdx] : a[j] > a[extIdx]) extIdx = j;
}
if (extIdx != i) swap(a, i, extIdx);
}
printArray(a, asc ? "選擇↑" : "選擇↓");
}
// ---------- 3. 直接插入排序 ----------
public void insertSort(int[] a, boolean asc) {
for (int i = 1; i < a.length; i++) {
int key = a[i], j = i - 1;
while (j >= 0 && (asc ? a[j] > key : a[j] < key)) {
a[j+1] = a[j];
j--;
}
a[j+1] = key;
}
printArray(a, asc ? "插入↑" : "插入↓");
}
// ---------- 4. 快速排序 ----------
public void quickSort(int[] a, boolean asc) {
qsort(a, 0, a.length - 1, asc);
printArray(a, asc ? "快速↑" : "快速↓");
}
private void qsort(int[] a, int lo, int hi, boolean asc) {
if (lo >= hi) return;
int p = partition(a, lo, hi, asc);
qsort(a, lo, p - 1, asc);
qsort(a, p + 1, hi, asc);
}
private int partition(int[] a, int lo, int hi, boolean asc) {
int pivot = a[lo];
int i = lo, j = hi;
while (i < j) {
while (i < j && (asc ? a[j] >= pivot : a[j] <= pivot)) j--;
if (i < j) a[i++] = a[j];
while (i < j && (asc ? a[i] <= pivot : a[i] >= pivot)) i++;
if (i < j) a[j--] = a[i];
}
a[i] = pivot;
return i;
}
// ---------- 5. 歸並排序 ----------
public void mergeSort(int[] a) {
int[] tmp = new int[a.length];
mergeSort(a, 0, a.length - 1, tmp);
printArray(a, "歸並↑");
}
private void mergeSort(int[] a, int l, int r, int[] tmp) {
if (l >= r) return;
int m = (l + r) >>> 1;
mergeSort(a, l, m, tmp);
mergeSort(a, m + 1, r, tmp);
merge(a, l, m, r, tmp);
}
private void merge(int[] a, int l, int m, int r, int[] tmp) {
int i = l, j = m + 1, k = 0;
while (i <= m && j <= r) tmp[k++] = (a[i] <= a[j]) ? a[i++] : a[j++];
while (i <= m) tmp[k++] = a[i++];
while (j <= r) tmp[k++] = a[j++];
System.arraycopy(tmp, 0, a, l, k);
}
// ---------- 6. 數組反轉 ----------
public void reverse(int[] a) {
for (int i = 0, j = a.length - 1; i < j; i++, j--) swap(a, i, j);
printArray(a, "反轉");
}
// ---------- 7. 二分查找(遞歸 + 迭代) ----------
public int binarySearchRec(int[] a, int key) {
return bsRec(a, key, 0, a.length - 1);
}
private int bsRec(int[] a, int key, int l, int r) {
if (l > r) return -1;
int m = (l + r) >>> 1;
if (key < a[m]) return bsRec(a, key, l, m - 1);
if (key > a[m]) return bsRec(a, key, m + 1, r);
return m;
}
public int binarySearchIter(int[] a, int key) {
int l = 0, r = a.length - 1;
while (l <= r) {
int m = (l + r) >>> 1;
if (key < a[m]) r = m - 1;
else if (key > a[m]) l = m + 1;
else return m;
}
return -1;
}
// ---------- 主測試入口 ----------
public static void main(String[] args) {
SortDemo demo = new SortDemo();
int[] arr;
arr = demo.createArray(); demo.bubbleSort(arr.clone(), true);
arr = demo.createArray(); demo.bubbleSort(arr.clone(), false);
arr = demo.createArray(); demo.selectSort(arr.clone(), true);
arr = demo.createArray(); demo.selectSort(arr.clone(), false);
arr = demo.createArray(); demo.insertSort(arr.clone(), true);
arr = demo.createArray(); demo.insertSort(arr.clone(), false);
arr = demo.createArray(); demo.quickSort(arr.clone(), true);
arr = demo.createArray(); demo.quickSort(arr.clone(), false);
arr = demo.createArray(); demo.mergeSort(arr.clone());
arr = demo.createArray(); demo.reverse(arr.clone());
// 二分查找演示(需先排序)
arr = demo.createArray(); demo.quickSort(arr, true);
int idx = demo.binarySearchIter(arr, 74);
System.out.println("二分查找 74 → 索引:" + idx + (idx >= 0 ? " (值=" + arr[idx] + ")" : " 未找到"));
}
}
(l+r)>>>1 防溢出,比除法快。Arrays.sort() / Collections.sort():JDK 使用雙軸快排(基本類型)與 TimSort(對象),經過極致優化。Comparator<T> 配合 Arrays.sort(T[], Comparator)。