Code:
import java.util.Arrays;
/**
* 歸併排序
*/
public class MergeSort {
/**
* 私有化
*/
private MergeSort() {}
/**
* 歸併排序的sort方法
* @param arr 待排序數組
* @param <E> 可比較的元素
*/
public static <E extends Comparable<E>> void sort(E[] arr) {
sort(arr, 0, arr.length - 1);
}
/**
* 內部sort方法
* @param arr 待排序數組
* @param l 左邊界索引
* @param r 右邊界索引
* @param <E> 元素類型(必須可比較)
*/
private static <E extends Comparable<E>> void sort(E[] arr, int l, int r) {
// 遞歸終止條件
if (l >= r) {
return;
}
// 分爲兩部分,取其中間索引(分治)
int mid = (l + r) / 2;
sort(arr, l, mid);
sort(arr, mid + 1, r);
// 將排好序的兩部分合二爲一(合併)
merge(arr, l, mid, r);
}
/**
* 合併兩個有序的區間 arr[l, mid] 和 arr[mid+1, r]
* @param arr 待排序數組(整個數組或部分)
* @param l 數組索引的左邊界
* @param mid 數組的中間索引
* @param r 數組索引的右邊界
* @param <E> 元素類型
*/
private static <E extends Comparable<E>> void merge(E[] arr, int l, int mid, int r) {
// 備份數組的[l, r]區間
E[] tmp = Arrays.copyOfRange(arr, l, r + 1);
// 指針i,指向左半部的開頭
int i = l;
// 指針j,指向右半部的開頭
int j = mid + 1;
// 爲[l, r]區間的arr排序
for (int k = l; k <= r; k++) {
// 如果i指針移動到了mid之外(右)
// 則說明數組左側部分已經全部遍歷過了
if (i > mid) {
arr[k] = tmp[j - l];
j++;
}
// 如果j指針也移動出了r邊界
// 則數組左側部分已經完成遍歷,這時處理左數組即可
else if (j > r) {
arr[k] = tmp[i - l];
i++;
}
// 如果i指針在左半邊數組的索引範圍內
// 且j指針也在右半邊數組的索引範圍之內
// 則比較i,j兩索引上的元素大小
else if (tmp[i - l].compareTo(tmp[j - l]) <= 0) {
// tmp[i] <= tmp[j]
arr[k] = tmp[i - l];
i++;
}
// 剩下的一種情況,i,j均未越界,且tmp[i] > tmp[j]
else {
arr[k] = tmp[j - l];
j++;
}
}
}
public static void main(String[] args) {
Integer[] arr = {9, -1, 5, 8, 2, 17, 7, 0, 6};
MergeSort.sort(arr);
for (int item : arr) {
System.out.println(item);
}
}
}