這周研究快速排序優化策略,首先是利用隨機化對快速排序進行優化。
眾所周知,之前的基礎快速排序算法,其效率一個關鍵點就在與划分元素的選取,由於之前一直選取的是第一個元素,所以當遇到特殊輸入,比如太大或者太小,就會造成區間划分極度不合理。
引入隨機化,就是在每一次划分的時候隨機選取一個元素作為關鍵字,用它來進行划分。由於每一次划分都是隨機選取,所以每一次都選到不好的元素概率低,可以作為一個優化的方向。
和之前的基礎快速排序主要區別有兩個
1.首先是partition部分
利用rand產生隨機數 ,其中flag是關鍵字的下標,通過隨機產生; pivotkey是對應該下標的數組元素值,;注意swap部分交換的是flag和high或者low,而不是之前基礎快拍的high和low互換;其次就是要注意隨機數產生要在low和high的范圍之內,可以通過設置偏移量(+low)來實現
1 int partition(int arr[], int low, int high) 2 { 3 4 int pivotkey, flag; 5 flag = (rand() % (high - low)) + low; 6 pivotkey = arr[flag]; 7 while (low < high) 8 { 9 while (low < high && (arr[high] >= pivotkey)) 10 { 11 high--; 12 } 13 if (low < high) 14 { 15 swap(arr, flag , high); 16 } 17 while (low < high && (arr[low] <= pivotkey)) 18 { 19 low++; 20 } 21 if (low < high) 22 { 23 swap(arr, flag, low); 24 } 25 } 26 return low; 27 }
2.swap部分,交換的元素改變了
1 void swap(int arr[], int &flag, int n) 2 { 3 int temp; 4 //先數組元素交換 5 temp = arr[flag]; 6 arr[flag] = arr[n]; 7 arr[n] = temp; 8 //再下標交換 9 10 flag = n; 11 }
下面放出完整代碼參考:
1 // 快速排序-隨機化優化 2 // 3 4 #include "stdafx.h" 5 #include <iostream> 6 #include <list> 7 #include <ctime> 8 9 using namespace std; 10 11 void swap(int arr[], int &flag, int n) 12 { 13 int temp; 14 //先數組元素交換 15 temp = arr[flag]; 16 arr[flag] = arr[n]; 17 arr[n] = temp; 18 //再下標交換 19 20 flag = n; 21 } 22 23 int partition(int arr[], int low, int high) 24 { 25 26 int pivotkey, flag; 27 flag = (rand() % (high - low)) + low; 28 pivotkey = arr[flag]; 29 while (low < high) 30 { 31 while (low < high && (arr[high] >= pivotkey)) 32 { 33 high--; 34 } 35 if (low < high) 36 { 37 swap(arr, flag , high); 38 } 39 while (low < high && (arr[low] <= pivotkey)) 40 { 41 low++; 42 } 43 if (low < high) 44 { 45 swap(arr, flag, low); 46 } 47 } 48 return low; 49 } 50 51 void qsort(int arr[], int low, int high) 52 { 53 int pivot; 54 if (low < high) 55 { 56 pivot = partition(arr, low, high); 57 qsort(arr, low, pivot - 1); 58 qsort(arr, pivot+1, high); 59 } 60 } 61 62 int _tmain(int argc, _TCHAR* argv[]) 63 { 64 int a[6] = { 11, 9, 5, 2, 2,0}; 65 66 qsort(a, 0, 5); 67 68 for (int i = 0; i <6; i++) 69 { 70 cout << a[i] << endl; 71 } 72 73 return 0; 74 }