归并排序:步骤讲解与代码实现
归并排序
在一些常用的排序中,归并排序在时间开销上来说可以是排序中的最佳实践之一(时间复杂度=n*log n),今天我们就来看看归并是如何实现的。
归并排序大致可以分为两步:
1、将数组从中间分开,对两边分别排序。
2、将两个有序的数组进行合并。
所以实现归并排序主要也就是解决这两个问题。
下图是归并排序的大致步骤,红线代表将数组拆开,蓝箭头代表将拆后的数组分别处理,红箭头代表将数组排序后返回
问题1:如何将数组分开,并进行分别排序?
答:使用递归实现
问题2:如何将两个有序的数组进行合并排序?
假设如上图的第二行中,需要合并(2,4,5,8)和(1,3,6,7)两个数组。
1,因为这两个数组都是增序的,只需要比较俩个数组的第一个数,那么比较小的数必然是两数组中最小的数。
例:比较(2,4,5,8)的2 和(1,3,6,7)的1,那么1必然是两数组中最小的数。
2,将这个数放入一个新的数组。
例:将1放入数组a[]中,两数组还有(2,4,5,8)的2 和(3,6,7)
3,再次重复第1步。
.....
如此比较直到其中一个数组结束,将另一个数组剩下的值全部放入数组a
那么数组a便是排好序的数组。
代码实现:
public class MergesSort { //排序函数,target为要排序的数组, // begin和end为要排序的区间的开始和结束坐标 public void mergeSort(int target[],int begin,int end){ //当要排序的数组区间只有一个数时直接返回 if((end-begin)==0){ return ; } //当排序的数组区间有两个数时,对这两个数进行比较 if((end-begin==1)){ sortS2B(target,begin,end); return ; } //当要排序的数组大于2个时,我们就分割此数组的区间,分别排序; int mid=(begin+end)/2; mergeSort(target,begin,mid); mergeSort(target,mid+1,end); //将排序好的俩数组的区间进行合并排序 //创建一个数组用于存放排好序的数组,大小就是区间大小 int temp[]=new int[end-begin+1]; //存放第一个数组的开始坐标 int p1=begin; //存放第二个数组的开始坐标 int p2=mid+1; //存放temp数组最近一次存放的数的坐标,初始为0 int p3=0;
while(p1<=mid&&p2<=end){ //将小的数存到temp数组 if(target[p1]<target[p2]){ temp[p3]=target[p1]; p3++; p1++; }else{ temp[p3]=target[p2]; p3++; p2++; } } //检查是否还有没有插入的 while(p1<=mid){ temp[p3]=target[p1]; p3++; p1++; } while(p2<=end){ temp[p3]=target[p2]; p3++; p2++; } //将排好的数组temp与原target的替换 System.arraycopy(temp, 0, target, begin, temp.length); }
//将数组target的a和b坐标的两个数按small to big从小到大排序 public void sortS2B(int target[],int begin,int end){ //如果begin>end,进行交换 if(target[begin]>target[end]){ int temp=target[begin]; target[begin]=target[end]; target[end]=temp; } return ; } public static void main(String[] args) { MergesSort ms=new MergesSort(); int a[]={8,-6,2,-7,9,-23,2,7,4,67,1,8}; //注意第三个参数是数组的结束坐标,应该因为数组是从0开始的,所以结束的坐标需要数组的长度-1 ms.mergeSort(a,0,a.length-1); int i=0; while(i<a.length){ System.out.print(a[i++]+" "); } } }
代码测试:
//测试代码 public static void main(String[] args) { MergesSort ms=new MergesSort(); int a[]={8,-6,2,-7,9,-23,2,7,4,67,1,8}; //注意第三个参数是数组的结束坐标,因为数组是从0开始的,所以结束的坐标需要数组的长度-1 ms.mergeSort(a,0,a.length-1); int i=0; while(i<a.length){ System.out.print(a[i++]+" "); } }
结果:
写此博客希望以后忘记的时候能够回顾一下,代码如果有不对的地方,请大佬们指正,谢谢~