排序之归并排序

归并是将两个有序的序列归并为一个有序序列,在这里,“两个有序序列”是指同一个序列中含有两部分“有序”的子序列,我们要做的就是把这两个有序的子序列“合并”,使其整体成为一个有序的序列。为了做到这一点,我们可以创建一个和原序列大小相同的空间(这里用数组表示),然后通过两个指针同时扫描原序列中的两个有序的子序列,将较小的数据放到我们新创建的数组中,最后得到的是一个有序的序列,然后将这个有序的序列拷贝的原序列中,这样就完成了原序列的归并。归并算法描述如下:

1、merge(array,left,mid,right)//这里array[left,mid],array[mid+1,right]是有序的子序列

2、  创建temArray,空间大小为right-left+1;

3、  定义临时变量i=left,j=mid+1,k=0;

4、  while(i<=mid && j<=right){

5、    if(array[i] < array[j]){

6、      temArray[k++]=array[i++];

7、    }else{

8、      temArray[k++]=array[j++];

9、    }

10、  }

11、  while(i<=mid){ temArray[k++]=array[i++]; }

12、  while(j<=right){ temArray[k++]=array[j++]; }

13、  for(i=0;i<k;i++){ array[left+i]=temArray[i]; }//将归并好的序列赋给原序列

那么,我们怎么划分"有序子序列"呢?鉴于递归的简洁性,我们可以用递归方法划分:对原序列进行二分,一直进行下去,直到得到的子序列是单个值的时候,单个值的子序列默认是有序的,然后再进行反向归并,如下图所示:

利用递归方法进行归并排序的完整程序如下:

public class Test{
    public static void main(String[] args)throws InterruptedException{
        int arr[]={1,4,23,0,4,5,34,23,4354,23,12,13};
        printArray(arr);
        merge_sort(arr,0,arr.length-1);
        printArray(arr);
    }
    
    static void merge_sort(int[] array,int left,int right){
        if(left<right){
            int mid=left+(right-left)/2;
            merge_sort(array,left,mid);
            merge_sort(array,mid+1,right);
            merge(array,left,mid,right);
        }
    }
    static void merge(int[] array,int left,int mid,int right){
        int[] temp=new int[right-left+1];
        int i=left,j=mid+1,k=0;//注意,这里的左右两边的子序列的下脚标与上面的调用一定要一致!尤其是右边子序列下脚标从哪开始从哪结束
        while(i<=mid && j<=right){ //i=left to mid-1;j=mid to right
            if(array[i]<array[j]){
                temp[k++]=array[i++];
            }else{
                temp[k++]=array[j++];
            }
        }
        while(i<=mid){
            temp[k++]=array[i++];
        }
        while(j<=right){//j=mid to right
            temp[k++]=array[j++];
        }
        for(i=0;i<k;i++){
            array[left+i]=temp[i];
        }
    }    
    static void printArray(int[] array){
        for(int val:array){
            System.out.print(val+" ");
        }
        System.out.println();
    }
}

归并排序算法性质:

1、归并排序算法的稳定性和归并算法有关,如果归并是稳定的,则归并排序也是稳定的。

2、归并排序算法的时间复杂度是O(nlgn),空间复杂度是O(n)。

3、归并排序算法的比较次数和序列的初始排序无关。

以上是个人总结,有误之处,请各位大侠指出

原文地址:https://www.cnblogs.com/codeMedita/p/7412568.html