归并排序 原文链接
归并排序是建立在归并操作上的排序算法,采用分治法,通过将已有的子序列合并,得到完全有序的序列,即先使每个子序列有序,在使子序列段间有序,将两个有序表合成一个有序表,称为二路归并。是一种稳定的排序算法。

思想
分而治之,将大的问题分成小的区间,进行递归求解,然后把小的区间合并。
排序流程

动图

代码
public static void mergeSort(int[] arr) {
sort(arr, 0, arr.length - 1);
}
public static void sort(int[] arr, int left, int right) {
if(left == right) {
return;
}
//找到中间位置下标
int mid =(left+right)/2;
//左路递归
sort(arr, left, mid);
//右路递归
sort(arr, mid + 1, right);
//合并数组
merge(arr, left, mid, right);
}
public static void merge(int[] arr, int left, int mid, int right) {
int[] temp = new int[right - left + 1];
int i = 0;
int p1 = left;
int p2 = mid + 1;
// 比较左右两部分的元素,哪个小,把那个元素填入temp中
while(p1 <= mid && p2 <= right) {
temp[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
// 上面的循环退出后,把剩余的元素依次填入到temp中
// 以下两个while只有一个会执行
while(p1 <= mid) {
temp[i++] = arr[p1++];
}
while(p2 <= right) {
temp[i++] = arr[p2++];
}
// 把最终的排序的结果复制给原数组
for(i = 0; i < temp.length; i++) {
arr[left+ i] = temp[i];
}
}
复杂度
- 时间复杂度:O(nlogn)
- 空间复杂度:O(N),归并排序需要一个与原数组相同长度的数组做辅助来排序
- 稳定性:归并排序是稳定的排序算法,temp[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];这行代码可以保证当左右两部分的值相等的时候,先复制左边的值,这样可以保证值相等的时候两个元素的相对位置不变。