归并排序(Merge Sort)

基本思想:

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。

归并排序示例:

 

Java 按照顺序合并视频 java合并两个有序列表_Java 按照顺序合并视频

合并方法:

设r[i…n]由两个有序子表r[i…m]和r[m+1…n]组成,两个子表长度分别为n-i +1、n-m。

  1. j=m+1;k=i;i=i; //置两个子表的起始下标及辅助数组的起始下标
  2. 若i>m 或j>n,转⑷ //其中一个子表已合并完,比较选取结束
  3. //选取r[i]和r[j]较小的存入辅助数组rf
    如果r[i]<r[j],rf[k]=r[i]; i++; k++; 转⑵
    否则,rf[k]=r[j]; j++; k++; 转⑵
  4. //将尚未处理完的子表中元素存入rf
    如果i<=m,将r[i…m]存入rf[k…n] //前一子表非空
    如果j<=n ,  将r[j…n] 存入rf[k…n] //后一子表非空
  5. 合并结束。
/*
     * 两个有序子列的归并,两个子列的长度都相等,为length
     * 两个有序子列归并后,存入在数组temp中
     */
    public static void merge(int[] a,int[] temp,int length,int l,int r){
        int begin = l;
        int leftend = r -1;
        int rightend = r+length-1;
        while(l<=leftend && r<=rightend){
            if(a[l] > a[r]){
                temp[begin++] = a[r++];
            }else{
                temp[begin++] = a[l++];
            }
        }
        while(r<=rightend){
            temp[begin++] = a[r++];
        }
        while(l<=leftend){
            temp[begin++] = a[l++];
        }
    }

一个无序的序列可以采用分而治之的思想:

(1)从长度为1的子序列开始归并,则变成了都是长度为2的有序子序列;

(2)按长度为2的子序列开始归并,则变成了都是长度为4的有序子序列;

(3)。。。。

(4)归并结束。




Java 按照顺序合并视频 java合并两个有序列表_子序列_02

序列归并的非递归算法

/*
     * 6、归并排序
     *  非递归归并实现 
     *  把一个序列,从0下标开始,先对1对数进行归并,然后再对2对数进行归并。。。
     */
    public static void merge_sort(int[] a,int n){
        int length = 1;//归并子序列的长度
        int[] temp = new int[n];
         while(length<n){
             merge_pass(a, temp, n, length);
             length *= 2;
             merge_pass(temp, a, n, length);
             length *= 2;
         }

    }
    /*
     * 完成一躺子序列归并
     * length为归并子序列的长度
     */
    public static void merge_pass(int[] a,int[] temp,int n,int length){
        int i = 0;
        for (; i <= n-2*length; i=2*length+i) {
            merge(a, temp, length, i, i+length);
        }
        if(i+length<n){//最后还剩下大于等于一个子列长度
            merge(a, temp, n-i-length, i, i+length);
        }else{//最后只剩下小于一个子列长度,则直接赋值
            for (int j = i; j < n; j++) {
                temp[j] = a[j];
            }
        }
        System.out.print("子列长为"+length+"归并: ");
        display(temp);
    }

    /*
     * 两个有序子列的归并,两个子列的长度都相等,为length
     * 两个有序子列归并后,存入在数组temp中
     */
    public static void merge(int[] a,int[] temp,int length,int l,int r){
        int begin = l;
        int leftend = r -1;
        int rightend = r+length-1;
        while(l<=leftend && r<=rightend){
            if(a[l] > a[r]){
                temp[begin++] = a[r++];
            }else{
                temp[begin++] = a[l++];
            }
        }
        while(r<=rightend){
            temp[begin++] = a[r++];
        }
        while(l<=leftend){
            temp[begin++] = a[l++];
        }
    }

测试代码:

public static void main(String[] args) {
        int[] a = {3,2,4,6,11,3,34,27,2,1,22,9,45,6};
        int[] temp = new int[a.length];
        System.out.print("子序列归并之前: ");
        display(a);
        merge_sort(a, a.length);
    }

结果为:

子序列归并之前: 3 2 4 6 11 3 34 27 2 1 22 9 45 6 
子列长为1归并: 2 3 4 6 3 11 27 34 1 2 9 22 6 45 
子列长为2归并: 2 3 4 6 3 11 27 34 1 2 9 22 6 45  
子列长为4归并: 2 3 3 4 6 11 27 34 1 2 6 9 22 45  
子列长为8归并: 1 2 2 3 3 4 6 6 9 11 22 27 34 45