Algs4-2.2.12次線性的額外空間O(N^2)時間複雜度

2.2.12次線性的額外空間。用大小M將數組分爲N/M塊(簡單起見,設M是N的約數)。實現一個歸併方法,使之所需的額外空間減小到max(M,N/M):(i)能夠先將一個塊看作一個元素,將塊的第一個元素做爲塊的主鍵,用選擇排序將塊排序;(ii)遍歷數組,將第一塊和第二塊歸併,完成後將第二塊和第三塊歸併,等等。
答:一個O(N^2)時間複雜度,O(M)空間複雜度的算法。
1)將a劃分紅N/M個單個長度最長爲M的子數組,對每一個子數組使用歸併排序算法排序。

2)將a劃分紅N/M個單個長度最長爲M子數組,以每一個子數組的第一個元素做爲排序關鍵字,使用選擇排序算法將各個子數組排序。對N/M個子數組排序,在歸併時會因歸併的兩段已有序而不用再歸併。

3)歸併子數組1和子數組2,再歸併子數組1~2和子數組3,再歸併子數組1~3和子數組4,直到歸併完子數組1~(N/M-1)和子數組N/M。例以下現的狀況(2,20,30)(3,5,8)(4,6,10),歸併前兩個後爲(2,3,5)(8,20,30)(4,6,10),此時若只歸併後面兩個子組數,歸併後的結果是(2,3,5)(4,6,8)(10,20,30)此時是無序的。若是在子數組1,2歸併後,再將1,2與子數組3歸併,獲得的結果(2,3,4)(5,6,8)(10,20,30)纔有序,因此此種採用了後段與全部前段歸併的方式,也所以造成O(N^2)時間複雜度,但也能夠當作是O((N/M)^2)時間複雜度。

4)若是歸併的兩段的交界值有序,那麼跳過本次歸併,無序時歸併這兩段。而後進行下一段與全部前段的歸併。歸併時先將後段長度爲M的子數組複製到輔助數組aux,而後將前段和輔組數組進行歸併,兩段中的大值從數組a的右邊歸併到左邊。
圖片

public class E2d2d12
{
    public static void sort(Comparable[] a,int M)
    {
       int N=a.length;
       Comparable[] aux=new Comparable[M];
       //sort each block elements, block size is 2*M
       for(int lo=0;lo<N;lo=lo+M)
           sort(a,aux,lo,lo+M-1);
       //sort all blocks with block first element
       SelectionSortBlock(a,M);
       //Merge
       for(int j=1;j<N/M;j++)
       {
           if (!less(a[j*M],a[j*M-1])) continue;
           Merge(a,aux,0,j*M-1,(j+1)*M-1);
       }
   }
   
    private static void sort(Comparable[] a,Comparable[] aux,int lo,int hi)
    {
        if (hi<=lo) return;
        int mid=lo+(hi-lo)/2;
        sort(a,aux,lo,mid);
        sort(a,aux,mid+1,hi);
        if (!less(a[mid+1],a[mid])) return;
        Merge(a,aux,lo,mid,hi);
    }
  
    //merge bigger value to the maxIndex of array a.
    private static void Merge(Comparable[] a,Comparable[] aux,int lo,int sp,int hi)
    {
        int M=hi-sp;
        //copy right half of array a to aux
        for(int i=0;i<M;i++)
            aux[i]=a[sp+1+i];
        //merge from array aux with left half  of a to  a
        int auxTop=M-1;
        int aTop=sp;
        for(int k=hi;k>=lo;k--)
        {
            if(auxTop<0) a[k]=a[aTop--];
            else if (aTop<lo) a[k]=aux[auxTop--];
            else if(less(aux[auxTop],a[aTop])) a[k]=a[aTop--];
            else a[k]=aux[auxTop--];
        }
    }
   
   private static void SelectionSortBlock(Comparable[] a,int M)
    {
        int length=a.length;
        int minIndex;
        for(int i=0;i<length;i=i+M)
        {
            minIndex=i;
            for(int j=i+M;j<length;j=j+M)
               if(less(a[j],a[minIndex])) minIndex=j;
            exch(a,i,minIndex,M);     
         }       
    }

      
    private static boolean less(Comparable v,Comparable w)
    {
        return v.compareTo(w)<0;
    }
   
     private static void exch(Comparable[] a,int i,int j,int length)
    {
        Comparable t;
        for(int index=0;index<length;index++)
        {
            t=a[i+index];
            a[i+index]=a[j+index];
            a[j+index]=t;
        }
    }
   
     public static boolean isSorted(Comparable[] a)
    {
        int len=a.length;
        for(int i=1;i<len;i++)
            if (less(a[i],a[i-1])) return false;
        return true;
    }
       
    public static void main(String[] args)
    {
        int N=Integer.parseInt(args[0]);
        int M=Integer.parseInt(args[1]);
        Double[] a=new Double[N];
        for(int i=0;i<N;i++)
            a[i]=StdRandom.uniform();
        sort(a,M);
        StdOut.printf("isSorted=%s",isSorted(a));
    }
}
問題中的max(M,N/M)沒有用到、將第一塊和第二塊歸併,完成後將第二塊和第三塊歸併等等沒有用到,塊排序對第一塊和第二塊,第二塊對第三塊的歸併的意義有沒有多是將時間複雜度降底到O(NlgN)的一個前提保證?若是是應該怎麼使用?很遺憾,可是下面的內容說明有更好的時間複雜度算法。 圖片算法

相關文章
相關標籤/搜索