算法设计与分析——自然合并排序(分治法)

算法的C++实现以及基本思想的图解说明,参考我之前的博客

https://www.cnblogs.com/wkfvawl/p/9772447.html

 

 

合并排序是利用分治策略对n个元素进行排序的算法,其基本思想是:将待排序元素分为大小大致相同的2个子集合,分别对这两个子集合进行排序,最终将排序好的子集合合并为所要求的的排好序的集合,递归写法如下:

    public static void mergeSort(Comparable []a,int left,int right)
    {
        if(left<right)
        {
            int mid = (left + right) / 2;      //取中点
            mergeSort(a,left,mid);             //左合并排序
            mergeSort(a,mid+1,right);          //右合并排序
            merge(a,b,left,right);             //合并到数组b
            copy(a,b,left,right);              //复制回数组a
        }
    }

其中,算法merge合并2个排序好的数组段到新的数组b中,然后由算法copy将合并后的数组段再复制回数组a中。算法merge和copy显然可以早O (n)时间内完成,因此对n个元素进行排序,最坏情况下所需要计算的时间T(n)满足

 

解此递归方程可知 T(n) = O(nlogn)。

 

 

按照此思想,消去递归后的合并排序可以描述为:

public static void mergeSort(Comparable []a)
    {
        Comparable []b = new Comparable[a.length];
        int s=1;
        while(s<a.length)
        {
            mergePass(a,b,s);          //合并到数组b
            s+=s;
            mergePass(b,a,s);          //合并回数组a
            s+=s;
        }
    }

其中,算法mergePass用于合并排好的相邻数组段。具体的合并算法由merge来实现。

public static void mergePass(Comparable []x,Comparable []y,int s)
    {
        int i=0;
        while(i<=x.length-2*s)
        {
            merge(x,y,i,i+s-1,i+2*s-1);
            i=i+2*s;
        }
        if(i+s<x.length)            //剩下的元素个数少于2s
        {
            merge(x,y,i,i+s-1,x.length-1);
        }
        else
        {
            //复制到y
            for(int j=i;j<x.length;j++)
            {
                y[j]=x[j];
            }
        }
    }

 

  public static void merge(Comparable[]c,Comparable[]d,int l,int m,int r)
    {
        int i=1;
        int j=m+1;
        int k=l;
        while((i<==m)&&(j<=r))
        {
            if(c[i].compareTo(c[j])<=0)  //c[i]<c[j]
            {
                d[k++]=c[i++];
            }
            else                         //c[i]>c[j]
            {
                d[k++]=c[j++]
            }
        }
        //将剩下的元素存到数组中
        while(i<=m)
        {
            d[k++]=c[i++];
        }
        while(j<=r)
        {
            d[k++]=c[j++];
        }
    }

 

posted @ 2019-09-07 13:52  王陸  阅读(4467)  评论(2编辑  收藏  举报