1. 程式人生 > >演算法導論第七章課後答案

演算法導論第七章課後答案

7.1-1 參照圖7-1的方法,說明PARTITION在陣列A={13,9,9,5,12,8,7,4,21,2,6,11}上的操作過程。

A={13,19,9,5,12,8,7,4,21,2,6,11}

  ={13,19,9,5,12,8,7,4,21,2,6,11}

  ={13,19,9,5,12,8,7,4,21,2,6,11}

  ={9,19,13,5,12,8,7,4,21,2,6,11}

  ={9,5,13,19,12,8,7,4,21,2,6,11}

  ={9,5,13,19,12,8,7,4,21,2,6,11}

  ={9,5,8,19,12,13,7,4,21,2,6,11}

  ={9,5,8,7,12,13,19,4,21,2,6,11}

  ={9,5,8,7,4,13,19,12,21,2,6,11}

  ={9,5,8,7,4,13,19,12,21,2,6,11}

  ={9,5,8,7,4,2,19,12,21,13,6,11}

  ={9,5,8,7,4,2,6,12,21,13,19,11}

  ={9,5,8,7,4,2,6,11,21,13,19,12}

7.1-2 當陣列A[p..r]中的元素都相同時,PARTITION返回的q值是什麼?修改PARTITION,使得當陣列A[p..r]中所有元素的值都相同時,q=(p+r)/2.

當元素相同時,q=i+1=r-1+1=r.

修改後的函式q=(p+r)/2.

int Partition(int A[], int p, int r)
{
   int x = A[r],i=p-1;
   int flag = 1;
   for (int j = p;j< r-1;j++)
   {
       if (x >=A[i]&&flag>0)//x=A[i]時,flag大於0和小於0的數量約為一半,
       {
           i = i + 1;
           swap(A[i],A[j]);
       }
       if (x ==A[i])
       {
           flag=-flag;//這樣就能讓i++次數減半。
       }
   }
    swap(A[i + 1],A[r]);
   return i + 1
}

7.1-3請簡要證明:在規模為n的子陣列上,PARTITION的時間複雜度為Θ(n)

除了函式內數個O(1),還有一個迴圈,其迴圈次數 p-(r-1)+1=p-r次,O(p-r)=O(n)

7.1-4  如何修改QUICKSORT,使得它能夠以非遞增序進行排序?

僅僅需要把  x >=A[i] 改為 x <=A[i]

7.2-1 利用帶入法證明:正如7.2節開頭提到的那樣,遞迴式T(n)=T(n-1)+Θ(n)的解為T(n)=Θ(n^2)  令Θ(n)=cn (c常數)。

 假設T(n)在n-1上成立。  先證明T(n)=Ο(n^2)

T(n)<=c1(n-1)^2+cn<=c1n^2 <=> (c-2c1)n+c1<=0 <=> c-2c1<0 (c<2c1) n>=c1/(2c1-c) 當0<c<2c1時,有n>=n0=c1/(2c1-c)  對於足夠大的n都成立。

再證明T(n)=Ω(n^2)  T(n)>=c2(n-1)^2+cn>=c2n^2  <=> (c-2c2)n+c2>=0 <=> c-2c2>0 (c>2c2>0) n>0 當c>2c2>0時,有n>0,對於足夠大的n都成立。

 所以存在常數c1>c/2,c2<c/2時,存在n0=max{c1/(2c1-c),0},使得當n>=n0時,對於足夠大的n都成立,T(n)=Θ(n^2)成立 

 7.2-2當陣列A的所有元素都具有相同值時,QUICKSORT的時間複雜度是什麼?  

 當陣列A所有元素相同時,QUICKSORT中的劃分時極為不平衡的,n-1:0的劃分,T(n)=T(n-1)+Θ(n)解這個遞迴式T(n)=Θ(n^2) 

 7.2-3 證明:當陣列A包含的元素不同,並且是按降序排列的時候,QUICKSORT的時間複雜度為Θ(n^2)

 按照降序排序時,在QUICKSORT中的劃分時極為不平衡的,n-1:0的劃分,所以其時間複雜度為T(n)=T(n-1)+Θ(n)解這個遞迴式  T(n)=T(n)=Θ(n^2)

 7.2-4 銀行一半會按照交易時間來記錄某一賬戶的交易情況。但是,很多人卻喜歡收到銀行對賬單是按照支票號碼的順序來排列的。這是因為,人們通常  都是按照支票號碼的順序來開出支票的,而商人也通常都是根據支票編號的順序兌付支票。這一問題時按照交易時間排序的序列轉換成按支票號排序的  序列,它是指上是一個對幾乎有序的輸入序列進行排序的問題。請證明:在這個問題上,INSERTION-SORT的效能往往要優於QUICKSORT?

插入排序在基本有序的情況下,基本無需移動任何元素來插入,所以只有外層迴圈了n次,所以時間複雜度為O(n)

 快速排序在基本有序的情況下,在劃分陣列時,劃分得非常不平衡,那麼其時間複雜度是O(nlgn),而達到完全有序時,時間 複雜度達到O(n^2),</p><p>所以總之插入排序要優於快速排序。 

7.2-5 假設快速排序的每一層所做的劃分的比例都是1-a:a,其中0<a<=1/2且是一個常數。是證明,在相應的遞迴樹中,葉結點的最小深度大約是  -lgn/lga,最大深度大約是-lgn/lg(1-a)(無需考慮整數舍入問題) 

 0<=a<=1/2  =>  a<1-a 只有T(1)時,到達樹底,設樹高度為k,所以就有  最小深度(a^k)n=1=>k=-lgn/lga 最大深度(1-a)^kn=1 => k=-lgn/lg(1-a)

 7.2-6試證明:在一個隨機輸入陣列上,對於任何常數0<a<=1/2,PARTITION產生比1-a:a更平衡的劃分的概率約為1-2a      

 設隨機陣列有n個數,則有A0,A1...Aan...A(1-a)n...An。</p><p>設X個數被劃分在左半部分,Y個數被劃分在右半部分。

則X+Y=n  那麼根據書上根據平衡的定義,X-Y差值越大,比例就越高,那麼越不平衡,只有X-Y差值越小,越接近0,X約等於Y的時候  越平衡。

 分三種情況討論:1)當X<a時,那麼Y>1-a, |X-Y|>1-2a>0               

                              2)當X>1-a時,那麼Y<a, |X-Y|>1-2a>0         

                              3)當a<X<1-a時,那麼a<Y<1-a,0<|X-Y|<1-2a

 只有當|X-Y|距離小於一個數時,才可能X-Y差值趨向於0,劃分的就越平衡。所以我們選擇情況3的這種劃分。  在an與(1-a)n之間取X的值,因為劃分X落在區間[0,n]上是等可能性的,所以符合均勻分佈,落在[an,(1-a)n}]上的任意一點  的概率也是等可能的,所以P{an≤x≤(1-a)n}=((1-a)n-an)/(n-0)=1-2a。得證! 

7.3-1 為什麼我們分析隨機化演算法的期望執行時間,而不是其最壞執行時間呢?

 隨機化演算法不能改變最壞情況下得執行時間,但是能降低最壞情況發生的概率。

  7.3-2在RANDOMIZED-QUICKSORT的執行過程中,在最壞情況下,隨機數生成器RANDOM被呼叫了多少次?在最好情況下呢? 

最好情況是均勻劃分,其時間複雜度 T(n)=2T(n/2)+1 =>主定理case1得T(n)=Θ(n)   

最壞情況是分成不平衡的劃分,其時間複雜度 T(n)=T(n-1)+T(0)+1 各式相加得=>T(n)=Θ(n)  

7.4-2 證明:在最好的情況下,快速排序的執行時間為Ω(nlgn)

最好情況就是均分的情況下,T(n)=2T(n/2)+Θ(n) 滿足主定理case2=>T(n)=Θ(nlgn)=Ω(nlgn)

7.4-4 證明:RANDOMIZED-QUICKSORT期望執行時間是Ω(nlgn).

根據書中7.4.2知:隨機化快速排序和普通快速排序就是主元選擇上有所不同,其他都相同。所以我們可以用分析普通快排的方法分析隨機快排,普通快排最好的情況是均分,其時間複雜度Ω(nlgn).,那麼快速排序的時間複雜度至少最好情況下的Ω(nlgn)。所以隨機化快排也是Ω(nlgn)。

7.4-5 當輸入資料已經集合有序時,插入排序速度很快。在實際應用中,我們可以利用這一特點來提高快速排序的速度。當對一個長度小於k的子陣列

呼叫快速排序時,讓它不做任何排序就返回。當上層的快速排序呼叫返回後,對整個陣列執行插入排序來完成排序過程。試證明,這一排序演算法的期望

時間複雜度為O(nk+nlg(n/k)).分別從理論和實踐的角度說明我們應該如何選擇k?

7.4-5的具體程式實現如下:

#include <iostream>
using namespace std;
int PARTITION(int A[],int p,int r)
{
    int x=A[r];
    int i=p-1;
    for (int j=p;j<=r-1;j++)//O(n)這裡應該包含第r-1個元素在迴圈裡
    {
        if (A[j]<=x)
        {
            i++;
            swap(A[i],A[j]);
        }
    }
    swap(A[i+1],A[r]);
    return i+1;
}
void QUICKSORT(int A[],int p,int r,int k)
{
    if (p<r&&r-p>=k)//T(n)=2
    {
        int q=PARTITION(A,p,r);
        QUICKSORT(A,p,q-1,k);
        QUICKSORT(A,q+1,r,k);
    }
}
void INSERTION_SORT(int A[],int r)
{
    int key;
    for (int j=1;j<=r;j++)
    {
        key=A[j-1];
        int i=j-1;
        while (i>0&&A[i-1]<key)//a)插入排序時間複雜度O(n^2)對於長度為k的子列表都有O(k^2),則n/k個為(k^2)*n/k=O(nk)
        {
            A[i]=A[i-1];
            i=i-1;
        }
        A[i]=key;
    }
}
void main()
{
    int A[16]={1,5,10,8,9,4,6,2,7,3,14,20,35,48,25,34};
    QUICKSORT(A,0,15,4);//K=3
    for (int i=0;i<16;i++)
    {
        cout<<A[i]<<" ";
    }
    cout<<endl;
    INSERTION_SORT(A,16);
    for ( i=0;i<16;i++)
    {
        cout<<A[i]<<" ";
    }
}

7.4-6 考慮對PARTITION過程做這樣的修改,從陣列A中隨機選出三個元素,並用這三個元素的中位數(既這三個元素按大小排在中間的值)對陣列進行

劃分。求以a的函式形式表示的,最壞劃分比例為a:(1-a)的近似概率,其中 0<a<1.

題目上說最壞劃分比例是a:(1-a),那麼由書中分析知 最壞劃分比例是0:(n-1)或是(n-1):0 這才是最壞劃分比例,所以
據我分析,題意應該是比a:(1-a)更壞的劃分比例。還有就是因為是隨機選取的3個元素並從中取中位數,那麼從0到n-1上的每個
元素都可以做主元,所以取出的中位數是等可能的,符合均勻分佈條件。
      設x為陣列前半部分的元素個數,y為陣列後半部分的元素個數。
當1<a<1/2時,a<1-a p(x<a)+p(x>1-a)+p(a<x<a-1)=1看7.2-6題已經給出答案。 x<a或者x>1-a時,劃分情況比a:(1-a)更壞,
更糟糕的概率是p(x<a∪x>1-a)=p(x<a)+p(x>1-a)=1-p(a<x<1-a)=1-(1-2a)=2a
同上可知,當1/2<a<1時,a>1-a p(x>a)+p(x<1-a)+p(a<x<1-a)=1 ,x>a或者x<1-a時,劃分情況比a:(1-a)更壞,更糟糕的概率
是p(x<1-a∪x>a)=p(x>a)+p(x<1-a)=1-p(a<x<1-a)=1-(2a-1)=2-2a