歸併排序採用 分治法:
時間複雜度 O(n log n),空間複雜度 O(n),穩定排序。
public class MergeSortRecursive {
private int[] aux; // 輔助陣列,避免重複分配
public void sort(int[] a) {
aux = new int[a.length];
sort(a, 0, a.length - 1);
}
private void sort(int[] a, int lo, int hi) {
if (lo >= hi) return;
int mid = lo + (hi - lo) / 2;
sort(a, lo, mid);
sort(a, mid + 1, hi);
merge(a, lo, mid, hi);
}
private void merge(int[] a, int lo, int mid, int hi) {
// 複製到輔助陣列
System.arraycopy(a, lo, aux, lo, hi - lo + 1);
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++) {
if (i > mid) a[k] = aux[j++];
else if (j > hi) a[k] = aux[i++];
else if (aux[i] <= aux[j]) a[k] = aux[i++]; // <= 保證穩定性
else a[k] = aux[j++];
}
}
public static void main(String[] args) {
int[] data = {38, 27, 43, 3, 9, 82, 10};
new MergeSortRecursive().sort(data);
System.out.println(Arrays.toString(data)); // [3, 9, 10, 27, 38, 43, 82]
}
}
public class MergeSortIterative {
public void sort(int[] a) {
int n = a.length;
int[] aux = new int[n];
for (int sz = 1; sz < n; sz *= 2) { // 子陣列大小 1,2,4,8...
for (int lo = 0; lo < n - sz; lo += 2 * sz) {
int mid = lo + sz - 1;
int hi = Math.min(lo + 2 * sz - 1, n - 1);
merge(a, aux, lo, mid, hi);
}
}
}
private void merge(int[] a, int[] aux, int lo, int mid, int hi) {
System.arraycopy(a, lo, aux, lo, hi - lo + 1);
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++) {
if (i > mid) a[k] = aux[j++];
else if (j > hi) a[k] = aux[i++];
else if (aux[i] <= aux[j]) a[k] = aux[i++];
else a[k] = aux[j++];
}
}
}
sz <= 7 時切換,減少遞迴開銷。a[mid] <= a[mid+1] 直接跳過。a、aux 角色,省去 System.arraycopy。| 特性 | MergeSort | Arrays.sort() (Dual-Pivot QuickSort) |
|---|---|---|
| 穩定性 | 穩定 | 不穩定 (基本型別) |
| 最壞時間 | O(n log n) | O(n²) (極罕見) |
| 空間 | O(n) | O(log n) |
| 適用場景 | 需穩定、外部排序、LinkedList | 一般用途、基本型別陣列 |
實務建議:生產碼直接用 Arrays.sort() 或 Collections.sort();教學、面試、特殊穩定性需求時手寫 MergeSort。