归并排序:步骤讲解与代码实现


归并排序 

  在一些常用的排序中,归并排序在时间开销上来说可以是排序中的最佳实践之一(时间复杂度=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++]+"  ");
        }
    }

结果:

写此博客希望以后忘记的时候能够回顾一下,代码如果有不对的地方,请大佬们指正,谢谢~