《大話資料結構》第9章 排序 9.6 希爾排序(下)_大話資料結構

來源:互聯網
上載者:User
9.6.3 希爾排序演算法

        好了,為了能夠真正弄明白希爾排序的演算法,我們還是老辦法——類比電腦在執行演算法時的步驟還研究演算法到底是如何進行排序的。
        希爾排序演算法代碼如下。

void ShellSort(SqList *L){    int i,j;    int increment=L->length;    do    {        increment=increment/3+1;            /* 增量序列 */        for(i=increment+1;i<=L->length;i++)        {            if (L->r[i]<L->r[i-increment])    /* 需將L->r[i]插入有序增量子表 */             {                 L->r[0]=L->r[i];             /* 暫存在L->r[0] */                for(j=i-increment;j>0 && L->r[0]<L->r[j];j-=increment)                    L->r[j+increment]=L->r[j]; /* 記錄後移,尋找插入位置 */                L->r[j+increment]=L->r[0]; /* 插入 */            }        }    }    while(increment>1);}

1) 程式開始運行,此時我們傳入的SqList參數的值為length=9,r[10]={0,9,1,5,8,3,7,4,6,2}。這就是我們需要等待排序的序列,如圖9-6-4所示。

2) 第4行,變數increment就是那個“增量”,我們初始值讓它等於待排序的記錄數。
3) 第5~19行是一個do迴圈,它提終止條件是increment不大於1時。其實也就是增量為1時就停止迴圈了。
4) 第7行,這一句很關鍵,但也是難以理解的地方,我們後面還要談到它,先放一放。這裡執行完成後,increment=9/3+1=4。
5) 第8~17行是一for迴圈,i從4+1=5開始到9結束。
6) 第10行,判斷L.r[i]與L.r[i-increment]大小,L.r[5]=3<L.r[i-increment]=L.r[1]=9,滿足條件,第12行,將L.r[5]=3暫存入L.r[0]。第13~14行的迴圈只是為了將L.r[1]=9的值賦給L.r[5],由於迴圈的增量是j-=increment,其實它就迴圈了一次,此時j=-3。第15行,再將L.r[0]=3賦值給L.r[j+increment]=L.r[-3+4]=L.r[1]=3。如圖9-6-5,事實上,這一段代碼就幹了一件事,就是將第5位的3和第1位的9交換了位置。


7) 迴圈繼續,i=6,L.r[6]=7>L.r[i-increment]=L.r[2]=1,因此不交換兩者資料。如圖9-6-6。

 

8) 迴圈繼續,i=7,L.r[7]=4<L.r[i-increment]=L.r[3]=5,交換兩者資料。如圖9-6-7。

9) 迴圈繼續,i=8,L.r[8]=6<L.r[i-increment]=L.r[4]=8,交換兩者資料。如圖9-6-8。

10) 迴圈繼續,i=9,L.r[9]=2<L.r[i-increment]=L.r[5]=9,交換兩者資料。注意,第13~14行是迴圈,此時還要繼續比較L.r[5]與L.r[1]的大小,因為2<3,所以還要交換L.r[5]與L.r[1]的資料,如圖9-6-9。


        最終第一輪迴圈後,數組的排序結果為圖9-6-10所示。細心的同學會發現,我們的數字1、2等小數字已經在前兩位,而8、9等大數字已經在後兩位,也就是說,通過這樣的排序,我們已經讓整個序列基本有序了。這其實就是希爾排序的精華所在,它將關鍵字較小的記錄,不是一步一步地往前挪動,而是跳躍式地往前移,從而使得每次完成一輪迴圈後,整個序列就朝著有序堅實地邁進一步。

 


11) 我們繼續,在完成一輪do迴圈後,此時由於increment=4>1因此我們需要繼續do迴圈。第7行得到increment=4/3+1=2。第8~17行for迴圈,i從2+1=3開始到9結束。當i=3、4時,不用交換,當i=5時,需要交換資料,如圖9-6-11



12) 此後,i=6、7、8、9均不用交換。如圖9-6-12


13) 再次完成一輪do迴圈,increment=2>1,再次do迴圈,第7行得到increment=2/3+1=1。此時這就是最後一輪do迴圈了。儘管第8~17行for迴圈,i從1+1=2開始到9結束,但由於當前序列已經基本有序,可交換資料的情況大為減少,效率其實很高。如圖9-6-13,圖中箭頭連線為需要交換的關鍵字。

 

最終完成排序過程,如圖9-6-14。

 


9.6.4 希爾排序複雜度分析
        通過這段代碼的剖析,相信大家有些明白,希爾排序的關鍵並不是隨便的分組後各自排序,而是將相隔某個“增量”的記錄組成一個子序列,實現跳躍式的移動,使得排序的效率提高。
        這裡“增量”的選取就非常關鍵了。我們在代碼中第7行,是用increment=increment/3+1;的方式選取增量的,可究竟應該選取什麼樣的增量才是最好,目前還是一個數學難題,迄今為止還沒有人找到一種最好的增量序列。不過大量的研究表明,當增量序列為dlta[k]=2t-k+1-1(0≤k≤t≤⌊log2(n+1)⌋)時,可以獲得不錯的效率,其時間複雜度為O(n3/2),要好於直接排序的O(n2)。需要注意的是,增量序列的最後一個增量值必須等於1才行。另外由於記錄是跳躍式的移動,希爾排序並不是一種穩定的排序演算法。
        不管怎麼說,希爾排序演算法的發明,使得我們終於突破了慢速排序的時代(超越了時間複雜度為O(n2)),之後,相應的更為高效的排序演算法也就相繼出現了。

出處:http://www.cnblogs.com/cj723/archive/2011/04/20/2021648.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.