归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并
public static int[] mergeSort(int[] array) {
// 后两个参数表示要进行归并排序的区间.
// [0, array.length)
// new 足够大的数组, 把这个数组作为缓冲区传给
// 递归函数
mergeSortHelper(array, 0, array.length);
return array;
}
private static void mergeSortHelper(int[] array, int left, int right) {
// [left, right) 构成了要去进行归并排序的区间
// 如果区间为空区间, 或者只有一个元素, 都不用排序
if (left >= right || right - left == 1) {
// 空区间或者区间只有一个元素, 都不需要进行归并排序
return;
}
// 使用类似后序遍历的方式.
// 先把当前的待排序区间拆成两半,
// 递归的对这两个子区间进行归并排序, 保证两个区间有序之后
// 再进行合并
int mid = (left + right) / 2;
// [left, mid)
// [mid, right)
mergeSortHelper(array, left, mid);
mergeSortHelper(array, mid, right);
merge(array, left, mid, right);
}
private static void merge(int[] array, int left,
int mid, int right) {
// 创建一段临时空间辅助进行归并
// 这个临时空间的长度应该是两个待归并区间的长度之和
int length = right - left;
int[] output = new int[length];
// 这个变量保存着当前 output 中的末尾元素的下标
int outputIndex = 0;
// i 和 j 是用来遍历两个区间的辅助变量
// [left, mid)
// [mid, right)
int i = left;
int j = mid;
while (i < mid && j < right) {
// 此处的 if 条件必须要 <= , 否则没法保证稳定性
if (array[i] <= array[j]) {
// i 对应的元素比 j 小
// 就把 i 对应的元素插入到 output 末尾
output[outputIndex++] = array[i++];
} else {
output[outputIndex++] = array[j++];
}
}
// 上面的循环结束之后, 两个区间至少有一个是遍历完了的.
// 就把剩下的区间的内容直接拷贝到 output 中即可.
while (i < mid) {
output[outputIndex++] = array[i++];
}
while (j < right) {
output[outputIndex++] = array[j++];
}
// 最后一步, 把 output 中的元素拷贝回原来的区间
for (int k = 0; k < length; k++) {
array[left + k] = output[k];
}
}
非递归:
public static int[] mergeSortByLoop(int[] array) {
// 借助下标相关的规律来进行分组.
// 初始情况下, 每个元素单独作为一组
// [0] [1] [2] [3] [4] [5]
// [0, 1] 和 [2, 3] 合并. [4, 5] 和 [6, 7] 区间合并
// [0, 1, 2, 3] [4, 5, 6, 7]
for (int gap = 1; gap < array.length; gap *= 2) {
for (int i = 0; i < array.length; i += 2 * gap) {
// 这个循环负责在 gap 为指定值的情况下
// 把所有的区间进行归并
// 针对当前的 i, 也能划分出两个需要进行归并的区间
// [beg, mid)
// [mid, end)
int beg = i;
int mid = i + gap;
int end = i + 2 * gap;
if (mid > array.length) {
mid = array.length;
}
if (end > array.length) {
end = array.length;
}
merge(array, beg, mid, end);//上述递归中的方法
}
}
return array;
}
来源:CSDN
作者:sun_105
链接:https://blog.csdn.net/sun_105/article/details/103242420