:不要忘記初心哈 :)
理論依據
快排算法的缺陷及其逐一改進
關於快速排序,無論是單路還是雙路亦或是三路快排,
有關其缺陷與優化辦法,
我在之前的一篇文章裏已經作出了詳細解讀.
具體鏈接如下:
如何在 Partition操作時,儘可能地 —— 劃分出
3等分的元素區間?
這邊是三路快排的改進策略.
三路快排儘可能三等份劃分區間
通過待排元素的區間長度劃分?
思路1:
利用待排序的區間長度,實現三等分劃分?
即:
(high - low)爲當前待排序區間[low,high]的長度.
令之劃分出三等分,然後再於中間部分隨機選取 哨兵元素.
(int)((high - low)/3.0*1.0)
(int)((high - low)/3.0*2.0)
可行度:(1——5評價)
3 顆星
利弊分析
如此設計,僅會在元素值與其索引值存在某種關聯時纔會產生巨大的優化效果.
雖說完全有序的數據往往與數組索引值存在關聯,
但是在處理其他完全隨機或者元素隨機範圍不大的數據時,優化適得其反.
通過待排元素的最值之差劃分?
思路1:
利用待排區間的最值元素之差,實現三等分劃分?
即:
maxNum 和 minNum 分別存放當前待排序區間的最大和最小元素值,
令之劃分出三等分,即
以 (maxNum - minNUm) 替代 (high - low),
然後再於中間部分隨機選取 哨兵元素.
可行度:(1——5評價)
2 顆星
利弊分析
如此設計,
當區間元素範圍較大時,多數情況下都會存在或多或少的優化效果.
可當區間元素範圍較小時(此時待排序區間通常也相對較小),
優化操作並不明顯甚至是適得其反,拖累程序性能.
快排到了中後期階段,
待排序的區間往往會變得很小,其中的元素值也會大小不相上下,
這種情況下,
最值元素之差就變得很小了,此時優化操作變爲拖累行爲.
另外,
更不用說若給出的數據直接是範圍極小、存在大量的重複元素的數組了,
如此情況下優化代碼幾乎沒有用處,
加強版三路快排已經退化爲三路快排,並且由於額外的設計開銷導致算法性能大不如前.
更加地適得其反!!
嚴重拖累程序性能!!!
直接使用待排元素的最大值劃分?
思路1:
直接利用待排區間的最大值元素,實現三等分劃分?
即:
maxNum 和 minNum 分別存放當前待排序區間的最大和最小元素值,
但是 僅以 maxNum 替代 (high - low),
然後再於中間部分隨機選取 哨兵元素.
可行度:(1——5評價)
5 顆星
利弊分析
經數據測試,這是一個普適版本的優化方式.
無論是元素完全隨機的情況,
還是元素隨機範圍極小、存在大量重複元素的情況,
甚至是兩兩相等、元素完全重複的數據
亦或是元素直接等於其索引值、完全線性沒有任何重複元素的情況,
或者是該情況元素先取反序之後再排序,
加強型三路快排都優勝與其他三種快排的設計.
這,
是我自己通過實驗數據、反覆操作嘗試得到的優化結果.
暫無使得其性能下降的反例數據.
實驗數據
大範圍隨機,重複元素極少
此種情況下有可能會存在少量的重複元素,不過
即使有往往也是極少的,
絕大多數情況下都不會多個重複的元素.
一千萬數據
測試一:1千萬數據,1億範圍隨機
測試二:1千萬數據,1千萬範圍隨機
測試三:1千萬數據,10萬範圍隨機
一個億數據
小範圍隨機,大量重複元素
此種情況下會存在大量的重複的元素.
由於此時單路快排的缺陷暴露無遺.
雖然三路快排擅長處理重複元素,但是性能還是不及改進後的加強型三路快排.
一千萬數據
測試一:1千萬數據,[10,20] 隨機範圍
測試二:1千萬數據,[10,100] 隨機範圍
一個億數據
測試一:1個億數據,[10,20] 隨機範圍
測試二:1個億數據,[10,100] 隨機範圍
測試三:1個億數據,[10,1000] 隨機範圍
當待排序的元素完全重複時
此種情況下元素完全重複、全部相等.
由於此時單路快排退化爲 O(N^2),無法參與數據測試.
理論上,處理完全重複的元素時,
改進後的加強型三路快排會退化爲經典的三路快排,
並且優化操作會造成額外開銷.
但是由於本設計細節的進一步改善之後,此兩者算法的開銷幾乎相同,
甚至有時候加強型三路快排還略微快出那麼一丟丟.
一千萬數據
測試一:1千萬數據,數值10
測試二:1千萬數據,數值10000
測試三:1千萬數據,數值1千萬
一個億數據
測試一:1個億數據,數值10
測試一:1個億數據,數值10萬
測試三:1個億數據,數值1千萬
當待排序的元素線性無重時
此種情況下元素完全不重複、沒有任何相等的兩個元素.
此時經典的三路快排性能堪憂,因爲其優化操作適得其反.
然而加強版三路快排卻依舊是佼佼者.
一千萬數據
測試一:1千萬數據,各個元素取對應的下標索引值,完全線性遞增、順序
測試二:1千萬數據,先完全線性遞增,再進行少量元素位置交換,局部有序
測試三:1千萬數據,對上述數組元素取反後再進行排序,完全遞降、逆序
測試四:1千萬數據,存在大量的局部逆序對的數據
實驗數據總結
無論任何類型的數據,加強型三路快排算法,
永遠是四種快排設計中的最優者.
這是由自己通過不斷試驗和測試數據,不斷改進代碼的設計方式得到的.
爲此,真的很欣慰!!!
通過實驗發現的一些規律
規律1:線性數據、無重複元素時,數據排列越混亂,快排運行處理的效率反而越高.
這是因爲快排的哨兵值劃分出的區間得以更加均勻和等長化。
規律2:經典算法設計的單路快排、雙路快排和三路快排,在處理局部有序的數據時,
處理大量順序對的數據要比處理逆序對的數據更快一些(排序結果爲升序).
但是加強版三路快排卻與之相反,處理由大到小的降序數據要比遞增的塊,這應該是
由自己的設計細節決定的,即前者能夠更加準確地獲取最大數值 MaxNum.
規律3:完全重複的數據,其數值大小並不會對任何一種快速排序產生影響; 普適.
關於實驗數據疑惑的解答
關於同一級別大小和同一數值範圍的實驗數據,
不同次的測試的實驗結果會存在一定的出入.
爲何如此?
因爲自己在設計快速排序時,標定點處(即哨兵值)是隨機選取的.
每一輪快排處理的區間都會隨機產生一個新的哨兵數值,
故而測試結果會有一定的差異.
代碼實現
由於此次三路快排的優化方式,是自己首創的.
不宜公開,:)
萬分抱歉,如果讓你感到不適的話.
不過,可以前來與我交流.
知識,不吝賜教!!!
不過這裏可以提供一篇文章,自己就是受到這篇文章的啓發進而實現了對
3路快排算法的進一步代碼優化.
不勝感激!!!
文章鏈接:一種三路劃分快速排序的改進算法
參考資料
有關快排的基本設計問題,建議看我之前的文章:
快排算法排序過程的圖形化演示,請參考:
排序算法過程演示
交流方式
QQ —— 2636105163(南國爛柯者)
溫馨提示:
轉載請註明出處!!
文章最後更新時間:
2020年3月30日05:07:14
2020年4月2日19:47:56