快速排序(quick_sort)
阿新 • • 發佈:2020-07-04
快速排序大體分為三個步驟:
1.確定分界點q[(l+r) >> 1]或者q[(l+r+1) >> 1],兩者得看情況而定,不能用q[(l]或者q[r]了 因為會超時。
2.調整區間範圍,讓小於等於x的放在左邊,大於等於x的數放在右邊。
3.遞迴處理左右兩端。
模板程式碼:
1 void quick_sort(int q[], int l, int r) 2 { 3 if(l >= r) return; 4 5 int x = q[(l+r) >> 1], i = l-1, j = r+1; //i為左邊指標 j為右邊指標 確定分界點6 7 while(i < j) //調整區間 8 { 9 do i++; while(q[i] < x); 10 do j--; while(q[j] > x); 11 if(i < j) swap(q[i], q[j]); 12 } 13 14 quick_sort(q, l, j); 15 quick_sort(q, j+1, r); 16 }
另外一種
void quick_sort(int q[], int l, int r) { if(l >= r) return; int x = q[(l+r+1) >> 1], i = l-1, j = r+1; //i為左邊指標 j為右邊指標 確定分界點 while(i < j) //調整區間 { do i++; while(q[i] < x); do j--; while(q[j] > x); if(i < j) swap(q[i], q[j]); } quick_sort(q, l, i-1); quick_sort(q, i, r); }
總的來說就是如果x取得是中間兩個數得下界(l+r+1 ) >> 1,那麼下邊遞迴得時候就得是用右指標即j與j+1,如果x取得是中間兩個數得上界(l+r+1) >> 1,那麼下邊遞迴得時候就得用左指標即i-1與i,不然會MLE,即超記憶體,就是進入了死迴圈。
錯位程式碼
1 void quick_sort(int q[], int l, int r) 2 { 3 if(l >= r) return; 4 5 int x = q[(l+r) >> 1], i = l-1, j = r+1; //i為左邊指標 j為右邊指標 確定分界點 6 7 while(i < j) //調整區間 8 { 9 do i++; while(q[i] < x); 10 do j--; while(q[j] > x); 11 if(i < j) swap(q[i], q[j]); 12 } 13 14 quick_sort(q, l, i-1); 15 quick_sort(q, i, r); 16 }
用一個樣例來說:假如n=2,樣例為1 2,最初i = -1,j = 2,x = 1 ,然後進行完while迴圈後,i與j都等於0,知識左邊區間遞迴的是0--1,然後根據if(l >= r) return;直接返回結束,然後遞迴右邊區間0--1,這是問題就來了,x仍然是1,繼續重複上一個過程,就進入了死迴圈,所以導致MLE,所以把程式改寫成q[(l+r+1) >> 1]即可通過。
最後快排模板題程式碼:
1 #include<iostream> 2 using namespace std; 3 4 const int N = 100010; 5 int n; 6 int q[N]; 7 8 void quick_sort(int q[], int l, int r) 9 { 10 if(l >= r) return; 11 12 int x = q[(l+r) >> 1], i = l-1, j = r+1; 13 while(i < j) 14 { 15 do i++; while(q[i] < x); 16 do j--; while(q[j] > x); 17 if(i < j) swap(q[i], q[j]); 18 } 19 20 quick_sort(q, l, j); 21 quick_sort(q, j+1, r); 22 } 23 24 int main() 25 { 26 scanf("%d", &n); 27 for(int i = 0; i < n; i++) scanf("%d", &q[i]); 28 29 quick_sort(q, 0, n-1); 30 31 for(int i = 0; i < n; i++) printf("%d ", q[i]); 32 33 system("pause"); 34 return 0; 35 }