一、三路快速排序算法的基本思想算法
以前的快速排序算法都是將序列分紅<=v和>v或者是<v和>=v的兩個部分,而三路快速排序是函數
將序列分紅三個部分:<v、=v、>v,以下圖所示:佈局
首先v元素仍是做爲"基準"元素,e表示當前遍歷索引值指向的元素,也就是待考慮的元素,從圖中能夠性能
看出來,整個序列被分紅3個部分,也就是說當咱們遍歷完成以後整個序列就已經被分紅了<v、=v、>v測試
三個部分了,而咱們只須要對<v和>v的兩個部分再次遞歸調用三路排序函數進行排序便可,來看看具體ui
的過程:spa
首先來看看整個序列的佈局,這裏咱們使用了3個索引值來表示3個不一樣的位置,使用lt索引來表示3d
<v部分和=v部分的分界處(這裏選的是<v部分的最後一個元素),使用i索引表示遍歷的位置,code
使用gt索引來表示=v部分和>v部分的分界處(這裏選的是>v部分的第一個元素)。blog
若是當前i指向的元素=v,那直接就將此元素歸爲=v部分,i++便可
若是當前i指向的元素<v,將此元素與=v部分的第一個元素
交換位置,也就是swap(arr[i], arr[lt+1]),以後將lt++,
i++便可,此時<v部分就多了一個元素
若是當前i指向的元素>v,則將此元素與>v部分的第一個元
素的前一個元素交換位置,也就是swap(arr[i], arr[gt-1]),
而後gt--,表示>v部分多了一個元素此時i不用動,由於他指
向的元素是交換過來的,這個元素尚未遍歷到。
當gt與i重合的時候就表示便利完畢了,那麼此時咱們只須要
將l指向的元素v與lt交換位置便可,以後就以下所示了
以後咱們只須要對<v和>v這兩部分再次遞歸進行三路排序,而對於=v的部分就不用在考慮了,由於他們
已經放在了合適的位置了,因此從這裏能夠看出來若是=v部分元素很是多,那麼咱們的三路快速排序算法
效果就會越明顯,這也正是他的優勢所在。
二、三路快速排序算法的實現(基於C++)
首先說明,代碼中使用到的索引值變量都是取之於上面的圖示中,這樣便於描述問題
1 /**************************************三路快速排序算法實現***********************************/ 2 template<typename T> 3 void __quickSort3Ways (T arr[], int left, int right) 4 { 5 if (right - left <= 40) { /* 對遞歸到數據量較小時使用插入排序 */ 6 __insertSortMG<T>(arr, left, right); 7 return; 8 } 9 10 std::swap(arr[left], arr[std::rand() % (right - left + 1) + left]); // 隨機化找到一個元素做爲"基準"元素 11 T v = arr[left]; 12 13 int lt = left; // 將<v的分界線的索引值lt初始化爲第一個元素的位置(也就是<v部分的最後一個元素所在位置) 14 int gt = right + 1; // 將>v的分界線的索引值gt初始化爲最後一個元素right的後一個元素所在位置(也就是>v部分的第一個元素所在位置) 15 int i = left + 1; // 將遍歷序列的索引值i初始化爲 left+1 16 17 while (i < gt) { // 循環繼續的條件 18 if (arr[i] < v) { 19 std::swap(arr[i], arr[lt + 1]); // 若是當前位置元素<v,則將當前位置元素與=v部分的第一個元素交換位置 20 i++; // i++ 考慮下一個元素 21 lt++; // lt++ 表示<v部分多了一個元素 22 } 23 else if (arr[i] > v) { // 若是當前位置元素>v,則將當前位置元素與>v部分的第一個元素的前一個元素交換位置 24 std::swap(arr[i], arr[gt - 1]); // 此時i不用動,由於交換過來的元素尚未考慮他的大小 25 gt--; // gt-- 表示>v部分多了一個元素 26 } 27 else { // 若是當前位置元素=v 則只須要將i++便可,表示=v部分多了一個元素 28 i++; 29 } 30 } 31 32 std::swap(arr[left], arr[lt]); // 上面的遍歷完成以後,將整個序列的第一個元素(也就是"基準"元素)放置到合適的位置 33 // 也就是將它放置在=v部分便可 34 __quickSort3Ways<T>(arr, left, lt - 1); // 對<v部分遞歸調用__quickSort3Ways函數進行三路排序 35 __quickSort3Ways<T>(arr, gt, right); // 對>v部分遞歸調用__quickSort3Ways函數進行三路排序 36 } 37 38 template<typename T> 39 void quickSort3Ways (T arr[], int count) 40 { 41 std::srand(std::time(NULL)); /* 種下隨機種子 */ 42 __quickSort3Ways<T>(arr, 0, count - 1); /* 調用__quickSort3Ways函數進行三路快速排序 */ 43 } 44 /***********************************************************************************************/
三、性能測試
通常排序序列:
大量重複元素序列:
近乎有序狀態的序列: