快速排序


【1】快速排序

快速排序是由托尼。霍爾(英文名C. A. R. Hoare,英國人,計算機領域爵士,同時是文科生獲圖靈獎者之一)於1962年提出的一種划分交換排序。

快速排序采用的是一種分治策略。快速排序經典之處在於它的排序思想。

所謂分治就是分而治之,從字面意思即可理解為:復雜問題簡單化,簡單問題重復化,重復問題高效化。所以,相比其它排序算法更快速。

而書面解釋為:將原問題分解為若干個規模更小但結構與原問題相似的子問題。遞歸地處理這些子問題,然后將這些子問題的解組合為原問題的解。

快速排序是一種不穩定的排序(參見隨筆《常用排序算法穩定性分析》)。

快速排序是時間復雜度是O(nlogn)。

【2】排序邏輯

設要排序的數組是A[0]~A[N-1]。(下面的例子中A[0]所為哨兵位,所謂哨兵位,即就是臨時寄存關鍵數據位置)

首先任意選取一個數據(通常選用第一個數據,在示例中從A[1]開始)作為關鍵數據,然后將所有比它大的數都放到它后面,所有比它小的數都放到它前面,這個過程稱為一趟快速排序。

一趟快速排序的算法是:

<1>設置兩個變量i, j,排序開始的時候:i = 1, j = N-1;

<2>以第一個數組元素(示例中即A[1])作為關鍵數據,賦值給A[0];

<3>從j開始向前搜索,即由后開始向前搜索(--j),找到第一個小於關鍵數據A[0]的值A[j], A[i] = A[j];

<4>從i開始向后搜索,即由前開始向后搜索(++i),找到第一個大於關鍵數據A[0]的值A[i], A[j] = A[i];

<5>重復3,4,5步,直到 i == j;

(注意:只有當i == j時,才可以完全確定當前關鍵數據可以插入的位置,即就是滿足比關鍵數據小的值全部置於其前,比關鍵數據大的值全部置於其后。)

【3】排序圖解(借用百度圖片)

該圖片很形象,全神貫注,仔細觀察:

【4】C++實現排序代碼

(1)C++實現排序詳細測試過程示例代碼:

 1 #include<iostream>
 2 using namespace std;  3 #define   MAXSIZE   10
 4 
 5 void PrintArr(int ar[],int n)  6 {  7     for(int i = 0; i < n; ++i)  8  {  9         cout<<ar[i]<<" ";  10  }  11     cout<<endl;  12 }  13 
 14 int nCount = 0;  15 
 16 int Partition(int br[], const int left, const int right)  17 {  18     ++nCount;  19     cout<<""<<nCount<<"趟排序過程如下:"<<endl;  20     int i = left, j = right;  21     cout<<"left = "<<left<<endl;  22      br[0] = br[left];    //注意哨兵位的作用:暫存本趟排序的關鍵數據
 23     cout<<"關鍵字:"<<br[0]<<endl;  24     cout<<"調整前順序:"<<endl;  25  PrintArr(br, MAXSIZE);  26     while(i < j)  27  {  28         while(i < j && br[j] > br[0])   //從末尾開始
 29  {  30             --j;      //前移一位
 31  }  32         br[i] = br[j];  //比關鍵字小的前置
 33         cout<<"比當前關鍵字大者調整結果:"<<endl;  34  PrintArr(br, MAXSIZE);  35         while(i < j && br[i] <= br[0])  //從前端開始
 36  {  37             ++i;    //后移一位
 38  }  39         br[j] = br[i];  //比關鍵字大的后置
 40         cout<<"比當前關鍵字小者調整結果:"<<endl;  41  PrintArr(br, MAXSIZE);  42  }  43     br[i] = br[0];  //插入關鍵字
 44  PrintArr(br, MAXSIZE);  45     cout<<"i = "<<i<<endl;  46     cout<<"本趟結束"<<endl;  47     return i;  48     
 49 }  50 
 51 void Quicksort(int br[],const int left,const int right)  52 {  53     if(left < right)  54  {  55         int mid = Partition(br, left, right);  56         Quicksort(br,left,mid-1);  57         Quicksort(br,mid+1,right);  58  }  59 }  60 
 61 void Quicksort(int br[],int n)  62 {  63     Quicksort(br, 1, n);  64 }  65 
 66 void main()  67 {  68     int ar[MAXSIZE] = {0, 14, 2, 58, 69, 100, 50, 26, 65, 97};  69     cout<<"排序前原數組"<<endl;  70  PrintArr(ar, MAXSIZE);  71     Quicksort(ar, MAXSIZE-1);  72     cout<<"排序后數組排序"<<endl;  73  PrintArr(ar, MAXSIZE);  74 
 75 }  76 /*
 77 排序前原數組  78 0 14 2 58 69 100 50 26 65 97  79 第1趟排序過程如下:  80 left = 1  81 關鍵字:14  82 調整前順序:  83 14 14 2 58 69 100 50 26 65 97  84 比當前關鍵字大者調整結果:  85 14 2 2 58 69 100 50 26 65 97  86 比當前關鍵字小者調整結果:  87 14 2 2 58 69 100 50 26 65 97  88 14 2 14 58 69 100 50 26 65 97  89 i = 2  90 本趟結束  91 第2趟排序過程如下:  92 left = 3  93 關鍵字:58  94 調整前順序:  95 58 2 14 58 69 100 50 26 65 97  96 比當前關鍵字大者調整結果:  97 58 2 14 26 69 100 50 26 65 97  98 比當前關鍵字小者調整結果:  99 58 2 14 26 69 100 50 69 65 97 100 比當前關鍵字大者調整結果: 101 58 2 14 26 50 100 50 69 65 97 102 比當前關鍵字小者調整結果: 103 58 2 14 26 50 100 100 69 65 97 104 比當前關鍵字大者調整結果: 105 58 2 14 26 50 100 100 69 65 97 106 比當前關鍵字小者調整結果: 107 58 2 14 26 50 100 100 69 65 97 108 58 2 14 26 50 58 100 69 65 97 109 i = 5 110 本趟結束 111 第3趟排序過程如下: 112 left = 3 113 關鍵字:26 114 調整前順序: 115 26 2 14 26 50 58 100 69 65 97 116 比當前關鍵字大者調整結果: 117 26 2 14 26 50 58 100 69 65 97 118 比當前關鍵字小者調整結果: 119 26 2 14 26 50 58 100 69 65 97 120 26 2 14 26 50 58 100 69 65 97 121 i = 3 122 本趟結束 123 第4趟排序過程如下: 124 left = 6 125 關鍵字:100 126 調整前順序: 127 100 2 14 26 50 58 100 69 65 97 128 比當前關鍵字大者調整結果: 129 100 2 14 26 50 58 97 69 65 97 130 比當前關鍵字小者調整結果: 131 100 2 14 26 50 58 97 69 65 97 132 100 2 14 26 50 58 97 69 65 100 133 i = 9 134 本趟結束 135 第5趟排序過程如下: 136 left = 6 137 關鍵字:97 138 調整前順序: 139 97 2 14 26 50 58 97 69 65 100 140 比當前關鍵字大者調整結果: 141 97 2 14 26 50 58 65 69 65 100 142 比當前關鍵字小者調整結果: 143 97 2 14 26 50 58 65 69 65 100 144 97 2 14 26 50 58 65 69 97 100 145 i = 8 146 本趟結束 147 第6趟排序過程如下: 148 left = 6 149 關鍵字:65 150 調整前順序: 151 65 2 14 26 50 58 65 69 97 100 152 比當前關鍵字大者調整結果: 153 65 2 14 26 50 58 65 69 97 100 154 比當前關鍵字小者調整結果: 155 65 2 14 26 50 58 65 69 97 100 156 65 2 14 26 50 58 65 69 97 100 157 i = 6 158 本趟結束 159 排序后數組排序 160 65 2 14 26 50 58 65 69 97 100 161 */

【2】中分析邏輯的第五條也就是為什么while(i < j ) 而不是 if(i <j )的原因提醒(也可以從上面的測試程序第二趟排序結果分析原因。)。

(2)完整快速排序實現代碼:

 1 int Partition(int br[], const int left, const int right)  2 {  3     int i = left, j = right;  4      br[0] = br[left];  5     while(i < j)  6  {  7         while(i < j && br[j] > br[0])  8  {  9             --j; 10  } 11         br[i] = br[j]; 12         while(i < j && br[i] <= br[0]) 13  { 14             ++i; 15  } 16         br[j] = br[i]; 17  } 18     br[i] = br[0]; 19     return i; 20     
21 } 22 
23 void Quicksort(int br[],const int left,const int right) 24 { 25     if(left < right) 26  { 27         int mid = Partition(br, left, right); 28         Quicksort(br,left,mid-1); 29         Quicksort(br,mid+1,right); 30  } 31 } 32 
33 void Quicksort(int br[],int n) 34 { 35     Quicksort(br, 1, n); 36 } 

關於快速排序的代碼,可以有很多種寫法,個人認為,此種寫法比較好理解,並且易於閱讀。

 

Good Good Study, Day Day Up.

順序  選擇  循環  堅持  總結


免責聲明!

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



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