三路快排算法加強版(三路快排的再次改進)







理論依據


快排算法的缺陷及其逐一改進

關於快速排序,無論是單路還是雙路亦或是三路快排,
有關其缺陷與優化辦法,
我在之前的一篇文章裏已經作出了詳細解讀.
具體鏈接如下:

快速排序(重溫經典算法系列)

如何在 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章