您的位置:首页 > 编程语言 > C语言/C++

c/c++--归并排序

2016-12-06 13:38 197 查看
归并排序,思想是将两个有序的数组归并成一个有序的数组。

它的时间复杂度是NlogN。

归并排序同时是分治算法的很好体现。

因为归并的前提是左右两边数组是有序的,因此我们得从最小的每两个长度开始进行归并,然后每4个长度开始归并,以此类推。

在较小长度的数组中,归并排序的效率无法证明与希尔排序的是快是慢,但是在较长长度的时候,是优于希尔排序的。

首先先理解归并的方法:

[java] view
plain copy

 





/** 

 * 归并方法 

 * @param a[] 一个有序的数组 

 * @param low 最低位下标 

 * @param mid 中间位下标 

 * @param height 最高位下标 

 */  

public static void merge(int[] a,int[] copyA, int low, int mid ,int height){  

  

    //复制到一个新的数组  

    for(int i=low;i<=height;i++){  

        copyA[i] = a[i];  

    }  

    //归并操作  

    //右边数组的第一个位置  

    int j = mid + 1;  

    for(int i=low;i<=height;i++){  

        //左边已经完全归并完成,右边的是有序的,因此只要把右边未归并完第一个放到a  

        // j++ 代表j当前位置被归并,然后处理下一个位置  

        if(i > mid){  

            a[i] = copyA[j++];  

        }else if(j > height){//右边已经被归并完成  

            a[i] = copyA[i++];  

        }else if(copyA[i] < copyA [j]){  

            a[i] = copyA[i];  

        }else{  

            a[i] = copyA[j];  

        }  

    }  

}  

自上而下的递归归并:
我们通过递归的方法自上而下递归调用自己:

[java] view
plain copy

 





/** 

     * 递归归并,自上而下的归并,从数组长度的一半开始,通过递归,当长度为2、4、8.。。。开始归并 

     * @param a 

     */  

    public static void sort1(int[] a){  

        int[] copyA = new int[a.length];  

        sort(a,copyA,0,a.length-1);  

        SortTest.isSorted(a);  

    }  

      

    /** 

     * 这里通过递归的方式,当长度间隔为1的时候开始归并,然后再是2,4、、、、 

     * @param a 

     * @param copyA 

     * @param low 

     * @param height 

     */  

    public static void sort(int[] a,int[] copyA, int low,int height){  

        if(low >= height){  

            return ;  

        }  

        int mid = (low + height)/2;  

        //归并前半部分  

        sort(a,copyA,low,mid);  

        //归并后半部分  

        sort(a,copyA,mid+1,height);  

        merge(a,copyA,low,mid,height);  

    }  

它的过程如下:



自下而上的归并:

[java] view
plain copy

 





/** 

     * 自下而上的归并,直接从长度间隔为1开始 

     * @param a 

     */  

    public static void sort2(int[] a){  

        int[] copyA = new int[a.length];  

        //复制到一个新的数组  

        for(int i=0;i<=a.length-1;i++){  

            copyA[i] = a[i];  

        }  

        //i代表循环次数  

        //e.g:0 1 2 3 4 5 6的循环过程是:  

        //01 23 45 6 --> 0123 456 --> 0123456  

        //次数为3次,因此i<=a.length/2  

        for(int i =0;i<=a.length/2;i++){  

            //j为具体归并的两个元素的下标  

            for(int j=0;j<a.length -i;j++){  

                merge(a,copyA,j,(j+j+i+1)/2,j+i+1-1);  

            }  

        }  

        SortTest.isSorted(a);  

    }  

它的过程如下:



原文地址:http://blog.csdn.net/qq_25412055/article/details/53472086?ref=myread
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: