简介
归并排序(merge sort)是一种采用了 分治 思想的排序算法。
工作原理
归并排序分为三个步骤:
- 将数列划分为两部分;
- 递归地分别对两个子序列进行归并排序;
- 合并两个子序列。
不难发现,归并排序的前两步都很好实现,关键是如何合并两个子序列。注意到两个子序列在第二步中已经保证了都是有序的了,第三步中实际上是想要把两个 有序 的序列合并起来。
性质
归并排序是一种稳定的排序算法。
归并排序的最优时间复杂度、平均时间复杂度和最坏时间复杂度均为 O ( n log n ) O(n\log n) O(nlogn)。
归并排序的空间复杂度为 O ( n ) O(n) O(n)。
代码实现
public static void mergeSort(int[] arr) {
if (arr.length == 0) {
return;
}
int[] result = mergeSort(arr, 0, arr.length - 1);
// 将结果拷贝到 arr 数组中
for (int i = 0; i < result.length; i++) {
arr[i] = result[i];
}
}
/**
* 对 arr 的 [start, end] 区间归并排序
*
* @param arr
* @param start
* @param end
* @return
*/
private static int[] mergeSort(int[] arr, int start, int end) {
// 只剩下一个数字,停止拆分,返回单个数字组成的数组
if (start == end) {
return new int[]{arr[start]};
}
int middle = (start + end) / 2;
// 拆分左边区域
int[] left = mergeSort(arr, start, middle);
// 拆分右边区域
int[] right = mergeSort(arr, middle + 1, end);
// 合并左右区域
return merge(left, right);
}
/**
* 将两个有序数组合并为一个有序数组
*/
private static int[] merge(int[] arr1, int[] arr2) {
int[] result = new int[arr1.length + arr2.length];
int index1 = 0, index2 = 0;
while (index1 < arr1.length && index2 < arr2.length) {
if (arr1[index1] <= arr2[index2]) {
result[index1 + index2] = arr1[index1];
index1++;
} else {
result[index1 + index2] = arr2[index2];
index2++;
}
}
// 将剩余数字补到结果数组之后
while (index1 < arr1.length) {
result[index1 + index2] = arr1[index1];
index1++;
}
while (index2 < arr2.length) {
result[index1 + index2] = arr2[index2];
index2++;
}
return result;
}
补充
归并排序就是个二叉树的后序遍历