Algs4-2.2.16自然的归并排序

2.2.16自然的归并排序。编写一个自底向上的归并排序,当需要将两个子数组排序时能够利用数组中已经有序的部分。首先找到一个有序的子数组(移动指针直到当前元素比上一个元素小为止),然后再找出另一个并将它们归并。根据数组大小和数组中递增子数组的最大长度分析算法的运行时间。
图片
import java.util.Arrays;
public  class E2d2d16
{
    public static void sort(Comparable[] a)
    {
      int N=a.length;
      if(N<=1) return;
      Comparable[] aux=new Comparable[N];
      int lo=0;
      int sp=-1;
      int hi=0;
      while(!(lo==0 && sp==N-1))
      {
        lo=0;
        while(lo<N-1)
        {
          sp=FindAscIndex(a,lo);
          hi=FindAscIndex(a,sp+1);
          if(sp==hi)
             break;
          else
           {
            merge(a,aux,lo,sp,hi);
            lo=hi+1;
          }//end if
        }//end while
      }//end while
    }

    
    private static int FindAscIndex(Comparable[] a,int lo)
    {
      int N=a.length;
      if (lo==N-1) return lo;
      else if(lo>N-1) return lo-1;
      int i;
      for(i=lo+1;i<N && !less(a[i],a[i-1]);i++);
      return i-1;  
    }
     
    private static void merge(Comparable[] a,Comparable[] aux,int lo,int sp,int hi)
    {
       for(int i=lo;i<=hi;i++)
         aux[i]=a[i];
       //
       int i=lo;
       int j=sp+1;
       for(int k=lo;k<=hi;k++)
       {
         if(i>sp) a[k]=aux[j++];
         else if(j>hi) a[k]=aux[i++];
         else if(less(aux[j],aux[i])) a[k]=aux[j++];
         else a[k]=aux[i++];
       }
    }
   
    public static boolean isSorted(Comparable[] a)
    {
      int N=a.length;
      for(int i=1;i<N;i++)
        if(less(a[i],a[i-1])) return false;
      return true;
    }
   
    private static boolean less(Comparable v,Comparable w)
    {
        return v.compareTo(w)<0;
    }
   
    public static void main(String[] args)
    {
      Integer N=Integer.parseInt(args[0]);
      Comparable[] a =new Comparable[N];
      for(int i=0;i<N;i++)
        a[i]=StdRandom.uniform();
      sort(a);
      StdOut.printf("a size is:%d,a is sorted=%s",a.length,isSorted(a));
   }
  
}
分析:
最坏情况:数组为逆序时,可以确保参与第一轮的归并的所有子数组的长度均为1,时此即为最坏情况。设数组长度为N=2^n,那么归并树深度为n,每一层查找子数组需要进行2N次数组访问,每一层归并需要2N次数组访问完成复制到辅助数组的操作,需要2N次数组访问完成比较,需要2N次访问完成辅助数组到a数组的复制,那么从底向上的自然归并最坏情况下需要访问8NlgN次数组。
最长子数组为k时:数组的最长子数组为k时,的最好情况是第一轮的所有子数组的长度均为k,设数组长度为N=K*2^m,那么归并树深库为m,每一层查找子数组需要进行2N次数组访问,每一层归并需要2N次数组访问完成复制到辅助数组的操作,需要2N次数组访问完成比较,需要2N次访问完成辅助数组到a数组的复制,那么从底向上的自然归并最坏情况下需要访问8Nlg(N/k)次数组操作。

posted @ 2018-10-27 09:15  修电脑的龙生  阅读(307)  评论(0编辑  收藏  举报