1.归并排序
前面我们介绍了快速排序和希尔排序,快速通过寻找基准数的方式将小于基准数放到基准数左边大于基准数的值放到右边,再递归排序。 希尔排序则是对数列进行分段,然后使用插入排序重新排序。是两种不同的思路 ,归档排序则是第三种不同的排序思路
- 平均时间复杂度O(nlogn)
- 最坏时间复杂度O(nlogn)
- 最好时间复杂度O(nlogn)
- 空间复杂度O(n)
- 是否稳定 稳定
二.思路
归并排序有几个关键点
1.low 排序数组的起点
2.height 排序数组的终点
3.mid 排序数组的中间点 也叫切割点
4.递归结束条件 low>=height 其实就是low==height
总思路是对数组进行无线对等切割,然后合并的时候排序,也叫分治法
这里需要注意的几个点
- 要合并的两个数组一定的排序好的数组
- 合并后的数组一定是排序好的
因此我们可以使用双指针的方法对两个数组进行排序
具体是开辟另一个数据空间,把两个数组的值从小到大放到数组里,当一个数组遍历完后,另一个数组的值一定是比临时数组大,并且是有序的,因此直接放到临时数组后即可,观察到这一点有助于我们理解并且书写算法
三.实现
/**
* 归并排序 思路 拆分 归并的同时排序
* @param array
* @return
*/
public static int[] split(int[] array,int low,int height){
if(low>=height){
return array;
}
int mid = (low+height)/2;
//拆分
split(array,low,mid);
split(array,mid+1,height);
//合并
return merge(array,low,height,mid);
}
public static int[] merge(int[] array,int low,int height,int mid){
//通过双指针排序
int left = low;
int right = mid+1;
//开辟临时数组空间
int[] temp = new int[height-low+1];
int tempIndex = 0;
//双指针对low->mid mid+1->height 两个数组进行排序 当一边遍历完 另一边没遍历的值一定比已经遍历的大
while(left<=mid && right<=height){
if(array[left]<array[height]){
temp[tempIndex++] = array[left++];
}else {
temp[tempIndex++] = array[right++];
}
}
//处理low->mid未遍历完的数据
while (left<=mid){
temp[tempIndex++] = array[left++];
}
while (right<=height){
temp[tempIndex++] = array[right++];
}
tempIndex--;
//将临时排序好的数组放到正式的数组中去 注意复制需要从下标low开始
while (tempIndex>=0){
array[low+tempIndex] = temp[tempIndex];
tempIndex--;
}
return array;
}