下面為一段普通的快速排序代碼
(1)隨機(jī)性
快速排序算法有較壞的情況,例如9、8、7、6、5、4、3、2、1這樣一個(gè)序列,此時(shí)用快速排序則效率很低。
因此,可以編寫shuffle函數(shù)打亂數(shù)組。
(2)采用三向切分
在實(shí)際應(yīng)用中,數(shù)組中可能存在著大量的重復(fù)元素,對(duì)重復(fù)元素進(jìn)行排序沒有任何意義。Dijkstra的三向切分解法思想如下圖所示。他使用了lt和gt指針,令[lo,...,lt-1]的元素都下于v,[gt+1,...,hi]的元素都大于v。
1、a[i]<v , swap(a[lt],a[i]) , lt++ , i++
2、a[i]>v , swap(a[gt],a[i]) , gt--
3、a[i]==v , i++
下圖為三向切分處理數(shù)組的過程:
(3)小規(guī)模數(shù)組采用直接插入排序
在快速排序遞歸的過程中,處理小規(guī)模數(shù)組時(shí),需要多次的遞歸,執(zhí)行更小的數(shù)組,導(dǎo)致此時(shí)快速排序沒有直接插入排序的效率高。因此將sort()中語(yǔ)句
if (hi <= lo) return;
替換成下面這條語(yǔ)句:
if ( hi <= lo + M) { Insertion.sort(a, lo, hi); return;}
其中M的最佳取值需要根據(jù)具體環(huán)境而定。
(4)設(shè)置哨兵
在插入排序時(shí),在數(shù)組0號(hào)元素存放哨兵,可以去除判斷指針是否小于數(shù)組的最低位的判斷。
(5)個(gè)人想法
在之前的學(xué)習(xí)中,學(xué)過歸并排序,它的復(fù)雜度為O(nlogn),但是快速排序優(yōu)化不采用歸并排序而采用三向切分,個(gè)人有以下兩點(diǎn)想法:
1、歸并排序?qū)χ貜?fù)數(shù)據(jù)的處理性能不穩(wěn)定。通過測(cè)試,隨機(jī)數(shù)組長(zhǎng)度為100000000,數(shù)字范圍為[0,200),自頂向下的歸并排序消耗時(shí)間為14427ms,三向切分消耗時(shí)間為13000ms。
2、小數(shù)組采用直接插入排序時(shí),M的取值在5~15之間性能較好,此時(shí)若對(duì)直接插入排序采用歸并,意義不大,可能還會(huì)因?yàn)檫f歸導(dǎo)致效率降低。