經典排序之 快速排序


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」,專注技術干貨分享,期待與你相遇。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM