- 这是一个纵使有千千万万不好,却在始终变得更好的国家----中国;
- 在集体和国家层面的大是大非前,能站出来奉献的伟大的人,不比六七十年代,隐姓埋名研究制衡核武器,导弹等的科学家、军人、人民群众少,只会更多;
- 感恩疫情抗战的所有人;
归并排序看了三四天,昨天总算是明白了一些,才动笔写下这篇文章。
一、什么是归并排序
归并排序的核心思想是分治思想,也就是将一个大的问题分割成类似的小问题,然后解决小问题,大问题就相应的解决了,这里面最核心的就是使用了递归。那么什么是递归呢,简单的说就是自己调用自己,但是光知道这个是远远不够的,递归中有几点个重要的性质,如下:
特别注意第四点和第五点:在一个函数内,递归调用的函数之前的语句,在这个递归语句之前执行,且顺序是一样的。但是递归调用函数之后的语句,先保留这个语句的所有状态,如果是函数,传入的参数也会保留,等待上面的递归函数执行完毕再回来执行,还有一点需要注意,就是递归了几次,递归调用函数之后的语句会反顺序执行,也就是说从最后一次递归时的状态,往第一次递归时的状态执行。
关于递归:参考以下链接:
你为什么学不会递归?读完这篇文章轻松理解递归算法
关于递归排序可以参考以下链接:
Java实现归并排序-有图有真相
二、归并排序算法
以下代码摘抄自https://blog.csdn.net/qq_36442947/article/details/81612870,改了一点点,大概意思就是那样的。
public class MergeSort {
//两路归并算法,两个排好序的子序列合并为一个子序列
public void merge(int []a,int left,int mid,int right){
int []tmp=new int[a.length];//辅助数组
int p1=left,p2=mid+1,k=left;//p1、p2是检测指针,k是存放指针
while(p1<=mid && p2<=right){
if(a[p1]<=a[p2])
tmp[k++]=a[p1++];
else
tmp[k++]=a[p2++];
}
while(p1<=mid) tmp[k++]=a[p1++];//如果第一个序列未检测完,直接将后面所有元素加到合并的序列中
while(p2<=right) tmp[k++]=a[p2++];//同上
//复制回原素组
for (int i = left; i <=right; i++)
a[i]=tmp[i];
}
public void mergeSort(int [] a,int start,int end){
if(start<end){//当子序列中只有一个元素时结束递归
int mid=(start+end)/2;//划分子序列
mergeSort(a, start, mid);//对左侧子序列进行递归排序
mergeSort(a, mid+1, end);//对右侧子序列进行递归排序
merge(a, start, mid, end);//合并
}
}
public class Test{
public static void main(String[] args) {
// 定义一个数组
Integer[]arr={6,5,4,7,1,70,9,0};
System.out.println("排序前的数组:"+Arrays.toString(arr));
// 调用方法,注意是静态方法,可以这样调用
mergeSort(arr);
System.out.println("排序前的数组:"+Arrays.toString(arr));
}
}
三、归并排序算法中递归的理解
之前我不理解的代码就在递归的地方,总是想不明白怎么一步步递归执行的,递归前的代码和递归后的代码又是怎么执行的,最终总算琢磨出来了,自己画了一个流程图: