基本思想
使用了分支的思想,用到了递归,有点像二分法的感觉,中间分开,左半边递归分开,右半边递归分开,直到分到最小,然后再排序组合
直接看图说话吧,还是尚学堂的图,有一说一他们课件真挺好的
疑惑
我并不觉得这种排序算法会好到哪里,他尽管把左右部分排好序了,但最后还是要再排一遍啊,比如这里
其实我不太明白这里
所以一会复习关键关注合治
而他的时间复杂度确实是O(nlogn)比插入,冒泡,希尔都要好
代码实现
public class MergeSort {
public static void main(String[] args) {
int[] arr = {8,4,5,7,1,3,6,2};
int[] temp = new int[arr.length];//归并排序需要一个额外空间
System.out.println("排序前数组为:"+ Arrays.toString(arr));
mergeSort(arr,0,arr.length-1,temp);
System.out.println("排序后数组为:"+ Arrays.toString(arr));
}
public static void mergeSort(int[] arr,int left,int right,int[] temp){
if (left<right){
int mid = (left+right)/2;//中间索引
//向左递归进行分解
mergeSort(arr,left,mid,temp);
//向右递归
mergeSort(arr,mid+1,right,temp);
//合并
merge(arr,left,mid,right,temp);
}
}
public static void merge(int[] arr,int left,int mid,int right,int[] temp){
int i = left;//初始化i,左边有序序列的初始索引
int j = mid + 1;//初始化j,右边有序序列的初始索引
int t = 0;//指向temp数组的当前索引
//1.先把左右两边(有序)的数据按照规则填充到temp数组,知道左右两边的有序序列又一边处理完为止
while (i<=mid&&j<=right){
if (arr[i]<arr[j]){
temp[t] = arr[i];
t+=1;
i+=1;
}else {
temp[t] = arr[j];
t+=1;
j+=1;
}
}
//2.把还有剩余数据的一边剩下的树填充到temp
while(i<=mid){
temp[t] = arr[i];
t++;
i++;
}
while (j<=right){
temp[t] = arr[j];
t++;
j++;
}
//3.将temp数组的元素拷贝到arr
//注意,不是每次都拷贝所有
t = 0;
int tempLeft = left;
while (tempLeft <= right){
arr[tempLeft] = temp[t];
t++;
tempLeft++;
}
}
}
她写了一个临时数组temp用来暂时存储’分’时排序的数组
比如左半边分到最后是[8],[4],然后在temp里{4,8}
在temp里先合起来,排一下序,他这里是使用了while进行排序,取出数,while循环比较找个合适的地方插进去,像插值排序。但他每次只循环该分支的部分,然后排好序了再把该段赋给arr
刚开始是两个值的循环,赋好值后,往上跳一层,四个值循环
左temp{4,5,7,8} arr{4,5,7,8,1,3,2,6}
右temp{1,2,3,6} arr{4,5,7,8,1,2,3,6}
再网上跳一层
{1,2,3,4,5,6,7,8}
他这个治的部分写的很好,我想不出来,重复看了两遍也只能是通过debug看懂他在干嘛,但能直接写出来还是很厉害的,这个代码我选择死记硬背一下,for 面试。
这个算法我GitHub上也有,但我把全部代码已经复制过来了,debug测试用这里的就好