思路來自 https://www.geeksforgeeks.org...ios
void qsort(vector<int>& vec, int low, int high) { if (low > high) return; int slow = low, pivot = vec[low]; // 要對**除了主元的全部元素**進行劃分,所以循環的邊界很好理解 for (int fast = low+1; fast <= high; ++fast) if (vec[fast] <= pivot) { // <= 或 < 都是對的~ slow++; swap(vec[slow], vec[fast]); } swap(vec[low], vec[slow]); // 劃分完成後再將主元放到其最終位置 qsort(vec, low, slow-1); qsort(vec, slow+1, high); }
思路就是,每次劃分(將數組小於等於pivot和大於pivot的元素分開)的時候,用一個慢指針和一個快指針。每當快指針掃描到小於等於pivot的元素,就將這個元素丟到慢指針的位置(同時慢指針增長)。慢指針指向的元素以及其左邊的元素,全都是被快指針丟過來的(也就是小於等於pivot的)。c++
之因此叫「慢」指針,是由於這個指針只有在快指針發現 【小於等於pivot的元素】的時候纔會增長,走得比快指針慢。
能夠想象到,快指針掃描過程當中的任什麼時候刻,慢指針指向、以及其左邊的元素都是小於等於pivot的,慢指針與快指針之間的元素都是大於pivot的。算法
在geeksforgeeks能夠測試其正確性。提交代碼:數組
#include <iostream> #include <vector> using namespace std; void swap(int& a, int& b) { int t = a; a = b; b = t; } void qsort(vector<int>& vec, int low, int high) { if (low > high) return; int slow = low, pivot = vec[low]; for (int fast = low+1; fast <= high; ++fast) if (vec[fast] <= pivot) { slow++; swap(vec[slow], vec[fast]); } swap(vec[low], vec[slow]); qsort(vec, low, slow-1); qsort(vec, slow+1, high); } void test() { int size; cin >> size; vector<int> vec(size); for (int i = 0; i < size; ++i) { cin >> vec[i]; } qsort(vec, 0, size-1); for (int i = 0; i < size; ++i) { cout << vec[i] << ' '; } cout << endl; return; } int main() { int testNum; cin >> testNum; while (testNum--) { test(); } return 0; }
其實這個算法不必定要選擇第一個元素做爲主元。若是你想選擇第i個元素做爲pivot,先將第i個元素與第一個元素交換一下,後面不就和剛纔的算法同樣了嗎~測試
最壞狀況:和其餘快排同樣,每次選擇pivot的時候都剛好選到了最大或最小的那個,對size爲n的數組進行劃分,獲得的倒是n-1的數組,所以要進行n次劃分。所以這種狀況下,時間複雜度爲n+(n-1)+(n-2)+....+0,也就是O(n^2)。ui