標籤:load form get targe -- seq cin size contain
小朋友學資料結構(7):快速排序
一、快速排序
(一)基本思想
選擇一個基準元素,通常選擇第一個元素或者最後一個元素,通過一趟掃描,將待排序列分成兩部分,一部分比基準元素小,一部分大於等於基準元素,此時基準元素在其排好序後的正確位置,然後再用同樣的方法遞迴地排序劃分的兩部分。
(二)例子 6-1.png
以{5, 9, 2, 7 ,8, 3, 6, 1, 4, 0}為例。
選擇第0個元素5作為參照數,咱們第一步的目標是把比5小的數都調整到5的左邊,比5大的數都調到5的右邊。
(1)從左往右開始觀察,發現9比5大,準備調整。再從右往左觀察,發現0比5小,準備調整。對調9和0的位置。
(2)繼續從左往右觀察,2比5小,不用調。繼續往右,7比5大,準備調整。繼續從右往左觀賽,4比5小,準備調整。對調7和4的位置。
(3)繼續從左往右觀察,8比5大,準備調整。繼續從右往左觀察,1比5小,準備調整。對調8和1的位置。
(4)繼續從左往右觀察,3比5小,不用調整。繼續往右觀察,碰到6,準備調整。繼續從右往左觀察,第一個碰到的就是6,這時從左往右或者從右往左碰到的都是6,所以6不用調,也不需要再繼續觀察下去了。
(5)最後一次調整一下3和5的位置。得到了第一步的目標,比5小的{3, 0, 2, 4, 1}都在5的左邊,比5大的{6, 8, 7, 9}都在5的右邊。
(6)對新數列{3, 0, 2, 4, 1}和{6, 8, 7, 9}分別用上面的方法繼續調整,直到所有的數都排完序為止。
注意,這裡是把第0個元素作為參照數。把別的元素作為參照數也是可以的。但是為了便於理解,通常要麼設第0個元素為參照數,要麼設中間元素為參照數。
下面的代碼是把中間元素設為參照數。
(三)C++代碼實現
#include<iostream>using namespace std;void quickSort(int a[], int l, int r){ int i = l, j = r, tmp; int pivot = a[(l + r) / 2]; // 比較的值,這裡是設成中間元素。若設成第一個元素也可以。 while(i <= j) { while(a[i] < pivot) { i++; } while(a[j] > pivot) { j--; } if(i <= j) { tmp = a[i]; a[i] = a[j]; a[j] = tmp; i++; j--; } } if(i < r) { quickSort(a, i, r); } if(l < j) { quickSort(a, l, j); }}int main(){ int a[] = {6, 1, 3, 2, 4, 5}; int len = sizeof(a) / sizeof(int); quickSort(a, 0, len - 1); for(int i = 0; i < len; i++) { cout << a[i] << ‘ ‘; } return 0;}
運行結果:
1 2 3
二、《大話資料結構》中的快速排序實現
具體內容見《大話資料結構》p417 - p433
#include<iostream>using namespace std;#define MAX 5typedef struct{ int r[MAX + 1]; int len;}seq;int partition(seq *x, int low, int high){ int pivotkey = x->r[low]; x->r[0] = pivotkey; while (low<high) { while (low < high && x->r[high] >= pivotkey) { high--; } x->r[low] = x->r[high]; while (low < high && x->r[low] <= pivotkey) { low++; } x->r[high] = x->r[low]; } x->r[low] = x->r[0]; return low;}void quicksort(seq *x, int low, int high){ int pivot; if(low < high) { pivot = partition(x, low, high); quicksort(x, low, pivot - 1); quicksort(x, pivot + 1, high); }}int main(){ seq s; for (int i = 1; i <= MAX; i++) { cin >> s.r[i]; } s.len = MAX; quicksort(&s, 1, s.len); for(int i = 1; i <= s.len; i++) { cout << s.r[i] << ‘ ‘; } cout << endl; return 0;}
運行結果:
1 2 3 4 5
注意,Swap函數裡有if判斷,理由可參考《小朋友學經典演算法(13):兩數交換》
https://www.jianshu.com/p/7c6ef94d5059
為何快速排序是不穩定的排序演算法:
以a[] = {5, 3, 3, 4, 3, 8, 9, 10}為例,
第一輪排序後,變成{3, 3, 3, 4 ,5, 8, 9, 10}這裡的第一個3,是原先的第三個3。
可見同一數值的先後順序亂了,所以是不穩定的。
小朋友學資料結構(7):快速排序