归并排序:
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,
该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
将已有序的子序列合并,得到完全有序的序列;
即先使每个子序列有序,再使子序列段间有序。
若将两个有序表合并成一个有序表,称为二路归并。
实现:
public static void mergeSort(int[] array) {
mergeSortInter(array, 0, array.length);
}
// 待排区间[low, high)
private static void mergeSortInter(int[] a, int low, int high) {
if (low >= high - 1) {
return;
}
int mid = (low + high) / 2;//没有考虑溢出
// [low, mid)
// [mid, high)
mergeSortInter(a, low, mid);
mergeSortInter(a, mid, high);
merge(a, low, mid, high);
}
原理–合并两个有序数组:
private static void merge(int[] a, int low, int mid, int high) {
int length = high - low;
int[] extra = new int[length];
int i = low;
int j = mid;
int k = 0;
while (i < mid && j < high) {
if (a[i] <= a[j]) {
extra[k++] = a[i++];
} else {
extra[k++] = a[j++];
}
}
while (i < mid) {
extra[k++] = a[i++];
}
while (j < high) {
extra[k++] = a[j++];
}
for (int x = 0; x < length; x++) {
a[low + x] = extra[x];
}
}
其性能分析:
稳定性:稳定
非递归版本:
public static void mergeSort3(int[] array) {
for (int i = 1; i < array.length; i = i * 2) {
for (int j = 0; j < array.length; j = j + 2 * i) {
int low = j;
int mid = j + i;
if (mid >= array.length) {
continue;
}
int high = mid + i;
if (high > array.length) {
high = array.length;
}
merge(array, low, mid, high);
}
}
}
海量数据的排序问题:
外部排序:排序过程需要在磁盘等外部存储进行的排序
前提:内存只有 1G,需要排序的数据有 100G
因为内存中因为无法把所有数据全部放下,所以需要外部排序,而归并排序是最常用的外部排序
1. 先把文件切分成 200 份,每个 512 M
2. 分别对 512 M 排序,因为内存已经可以放的下,所以任意排序方式都可以
3. 进行 200 路归并,同时对 200 份有序文件做归并过程,最终结果就有序了
其他:
二路归并:两个有序数组合并成一个有序数组
m路归并:m个有序数组合并成一个有序数组