《大话数据结构》第9章 排序 9.8 归并排序(下)
9.8.3?歸并排序復(fù)雜度分析
????????我們來分析一下歸并排序的時(shí)間復(fù)雜度,一趟歸并需要將SR[1]~SR[n]中相鄰的長(zhǎng)度為h的有序序列進(jìn)行兩兩歸并。并將結(jié)果放到TR1[1]~TR1[n]中,這需要將待排序序列中的所有記錄掃描一遍,因此耗費(fèi)O(n)時(shí)間,而由完全二叉樹的深度可知,整個(gè)歸并排序需要進(jìn)行?log2n?趟,因此,總的時(shí)間復(fù)雜度為O(nlogn),而且這是歸并排序算法中最好、最壞、平均的時(shí)間性能。
????????由于歸并排序在歸并過程中需要與原始記錄序列同樣數(shù)量的存儲(chǔ)空間存放歸并結(jié)果以及遞歸時(shí)深度為log2n的棧空間,因此空間復(fù)雜度為O(n+logn)。
????????另外,對(duì)代碼進(jìn)行仔細(xì)研究,發(fā)現(xiàn)Merge函數(shù)中有if (SR[i]<SR[j])語句,這就說明它需要兩兩比較,不存在跳躍,因此歸并排序是一種穩(wěn)定的排序算法。
????????也就是說,歸并排序是一種比較占用內(nèi)存,但卻效率高且穩(wěn)定的算法。
9.8.4?非遞歸實(shí)現(xiàn)歸并排序
????????我們常說,“沒有最好,只有更好。”歸并排序大量引用了遞歸,盡管在代碼上比較清晰,容易理解,但這會(huì)造成時(shí)間和空間上的性能損耗。我們排序追求的就是效率,有沒有可能將遞歸轉(zhuǎn)化成迭代呢?結(jié)論當(dāng)然是可以的,而且改動(dòng)之后,性能上進(jìn)一步提高了。來看代碼。
1)?程序開始執(zhí)行,數(shù)組L為{50,10,90,30,70,40,80,60,20},L.length=9。
2)?第3行,我們事先申請(qǐng)了額外的數(shù)組內(nèi)存空間,用來存放歸并結(jié)果。
3)?第5~11行,是一個(gè)while循環(huán),目的就不斷的歸并有序序列。注意k值的變化,第8行與第10行,在不斷循環(huán)中,它將由1→2→4→8→16,跳出循環(huán)。
4)?第7行,此時(shí)k=1,MergePass函數(shù)將原來的無序數(shù)組兩兩歸并入TR,此函數(shù)代碼稍后再講。如圖9-8-11。
?
5)?第8行,k=2
6)?第9行,MergePass函數(shù)將TR中已經(jīng)兩兩歸并的有序序列再次歸并回?cái)?shù)組L.r中,如圖9-8-12。
?
7)?第10行,k=4,因?yàn)閗<9,所以繼續(xù)循環(huán),再次歸并,最終執(zhí)行完第7~10行,k=16,結(jié)束循環(huán),完成排序工作。如圖9-8-13。
?
????????從代碼中,我們能夠感受到,非遞歸的迭代做法更加直截了當(dāng),從最小的序列開始?xì)w并直至完成。不需要像歸并的遞歸算法一樣,需要先拆分遞歸,再歸并退出遞歸。
????????現(xiàn)在我們來看MergePass代碼是如何實(shí)現(xiàn)的。
?
/* 將SR[]中相鄰長(zhǎng)度為s的子序列兩兩歸并到TR[] */ void MergePass(int SR[],int TR[],int s,int n) {int i=1;int j;while(i <= n-2*s+1) { Merge(SR,TR,i,i+s-1,i+2*s-1); /* 兩兩歸并 */i=i+2*s; }if(i<n-s+1) /* 歸并最后兩個(gè)序列 */Merge(SR,TR,i,i+s-1,n);else /* 若最后只剩下單個(gè)子序列 */for(j =i;j <= n;j++)TR[j] = SR[j]; }1)?程序執(zhí)行。我們第一次調(diào)用“MergePass(L.r,TR,k,L.length);”,此時(shí)L.r是初始無序狀態(tài),TR為新申請(qǐng)的空數(shù)組,k=1,L.length=9。
2)?第5~9行,循環(huán)的目的就兩兩歸并,因s=1,n-2*s+1=8,為什么循環(huán)i從1到8,而不是9呢?就是因?yàn)閮蓛蓺w并,最終9條記錄定會(huì)剩下來,無法歸并。
3)?第7行,Merge函數(shù)我們前面已經(jīng)詳細(xì)講過,此時(shí)i=1,i+s-1=1,i+2*s-1=2。也就是說,我們將SR(即L.r)中的第一個(gè)和第二個(gè)記錄歸并到TR中。然后第8行,i=i+2*s=3,再循環(huán),我們就是將第三個(gè)和第四個(gè)記錄歸并到TR中,一直到第七和第八個(gè)記錄完成歸并。如圖9-8-14。
?
4)?第10~14行,主要是處理最后的尾數(shù)的,第11行是說將最后剩下的多個(gè)記錄歸并到TR中。不過由于i=9,n-s+1=9,因此執(zhí)行第13~14行,將20放入到TR數(shù)組的最后。
?
?
5)?再次調(diào)用MergePass時(shí),s=2,第5~9行的循環(huán),由第8行的i=i+2*s可知,此時(shí)i就是以4為增量進(jìn)行循環(huán)了。也就是說,是將兩個(gè)有兩個(gè)記錄的有序序列進(jìn)行歸并為四個(gè)記錄的有序序列。最終再將最后剩下的第九條記錄“20”插入TR。
?
6)?后面的類似,略。
????????非遞歸的迭代方法,避免了遞歸時(shí)深度為log2n的棧空間,空間只是用到申請(qǐng)歸并臨時(shí)用的TR數(shù)組,因此空間復(fù)雜度為O(n)。并且避免遞歸也在時(shí)間性能上有一定的提升,應(yīng)該說,使用歸并排序時(shí),盡量考慮用非遞歸方法。? 出處:http://www.cnblogs.com/cj723/archive/2011/04/26/2026886.html
總結(jié)
以上是生活随笔為你收集整理的《大话数据结构》第9章 排序 9.8 归并排序(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《大话数据结构》第9章 排序 9.8 归
- 下一篇: 《大话数据结构》第9章 排序 9.9 快