Author: bakari Date: 2012.7.21
排序算法有很多種,每一種在不同的情況下都占有一席之地。關於排序算法我分“經典排序之”系列分別述之。本篇為快排。
快排是一個非常重要的算法,在各個領域幾乎都有它的身影,尤其是文件檢索這一塊。運用一個好的排序算法是衡量一個軟件優劣的關鍵因素,下面我就此總結一下快排的幾種經典的情況:
轉載引用請注明出處:http://www.cnblogs.com/bakari/archive/2012/08/11/2633545.html 謝謝!
我是用C++的類寫的,存儲結構為vector(這個無所謂),本來一個通用的快排函數應該是QuickSort(str, left ,right);
有了類之后我改寫成了QuickSort(left, right);不過沒關系,代碼,函數都不重要,重要的是懂得算法的本質。
快排關鍵之處在於選取基准元素,根據基准元素所在的位置可以分為三種情況,下面分別述之。文中實例程序皆已測試通過。
關於快排的理解我不想多講,簡單地說就是給一個數據序列划分界限,小的放前面,大的放后面,然后在前域和后域分別遞歸進行。
如果想知道VC庫中的快排函數的原理:請參考我的另一篇文章:
VC庫中的快排函數詳解:http://www.cnblogs.com/bakari/archive/2012/08/11/2633453.html
如果不懂的童鞋可以參考下面這個視頻,這是我在網上找的一個超級形象的視頻,懂的童鞋可以直接跳過,本文重點在於總結算法。
http://v.youku.com/v_show/id_XMzMyODk4NTQ4.html
1、基准元素選擇第一個元素:
1 /****************************************************************** 2 * Author: bakari Date :2012.7.21 3 * 快速排序 4 * 算法重點:選基准元素:比基准元素小的放前面,比基准元素大的放后面 5 * 第一種:基准元素選第一個元素 6 * 第二種:基准元素選中間元素 7 * 第三種:基准元素選序列最后一個元素 8 * 第三種算法關鍵在於找合適的位置將最后一個元素插入,然后在其兩邊在運用快排。 9 ******************************************************************/ 10 11 /* 基准元素是第一個 */ 12 void QuickSort::Quick_Sort1(int left,int right) 13 { 14 int iLeft = left; 15 int iRight = right; 16 int temp = QuickList[left]; //取第一個元素作為基准元素 17 while(iLeft < iRight) 18 { 19 while (iLeft < iRight && QuickList[iRight] >= temp) iRight --; 20 if (iLeft < iRight){ 21 Swap(iLeft,iRight); 22 23 /* 這里有兩種途徑:交換和替換都可以,改動相應地方就可以了 */ 24 /* 第二種方法 如文中注釋的地方 */ 25 //QuickList[iLeft] = QuickList[iRight]; 26 //iLeft++; 27 28 } 29 while (iLeft < iRight && QuickList[iLeft] <= temp) iLeft ++; 30 if (iLeft < iRight){ 31 Swap(iLeft,iRight); 32 //QuickList[iRight] = QuickList[iLeft]; 33 //iRight--; 34 } 35 } 36 //QuickList[iLeft] = temp; 37 if (iLeft != left) Quick_Sort1(left,iLeft - 1); 38 if (iRight != right) Quick_Sort1(iRight + 1,right); 39 }
2、基准元素選中間(最好的)
1 /* 基准元素是中間個 */ 2 void QuickSort::Quick_Sort2(int left,int right) 3 { 4 int iLeft = left; 5 int iRight = right; 6 int iMiddle = (iLeft + iRight) / 2; //選中間元素 7 int temp = QuickList[iMiddle]; 8 9 while (1) 10 { 11 while (QuickList[iRight] > temp) iRight--; 12 while (QuickList[iLeft] < temp) iLeft++; 13 if(iLeft >= iRight) break; 14 Swap(iLeft,iRight); //交換 15 } 16 17 if(iLeft != left) Quick_Sort2(left,iLeft - 1); //遞歸調用 18 if(iRight != right) Quick_Sort2(iRight + 1,right); 19 }
3、基准元素選最后一個
這個是我之前沒遇到過的,上課的教材也沒有,老師也沒講,我也自己寫過,可見,自己有多被動。這兒是我前兩天看左飛的書時不小心看到的,個人覺得還蠻經典的。讓我思維一下子開闊起來。
先說明這個快排的概念,先以最右邊的s為標准,分為三部分,小於s的部分,大於s 的部分和未處理的。如下圖:

在排序過程中 i 和 j 會不斷地往右進行比較和交換,最后變成:

然后s值置於中間,按相同的方法再在左右區域進行相同的動作。如:

一個實際例子的演算如下:

代碼展示:
1 void QuickSort::Quick_Sort3(int left,int right) 2 { 3 4 if (left < right) 5 { 6 int p = FindPosition(left,right); 7 Quick_Sort3(left,p - 1); 8 Quick_Sort3(p + 1,right); 9 } 10 } 11 12 /* 找最后一個元素的合適位置 */ 13 int QuickSort::FindPosition(int left,int right) 14 { 15 int i = left - 1; 16 int iFind = QuickList[right]; 17 for (int j = left;j != right;++j) 18 { 19 if (QuickList[j] <= iFind) 20 { 21 i++; 22 Swap(i,j); 23 } 24 } 25 Swap(i + 1,right); 26 return (i + 1); 27 28 }
OK,目前我知道的快排就有這三種,熟練掌握着三種排序就OK了。
轉載引用請注明出處:http://www.cnblogs.com/bakari/archive/2012/08/11/2633545.html 謝謝!
開了個公眾號「aCloudDeveloper」,專注技術干貨分享,期待與你相遇。

