排序算法哪家強,從實際應用的角度上將,快排表現很好。很天然地,人們會以爲短數組比長數組更好處理,所以可能會想到將原始數組分爲若干各子部分而後分別進行排序。快速排序就是基於分治法的排序算法,這不過它更多地側重於「分」,沒有明顯的「合」過程。ios
1.快排算法的主要思想:算法
5. 快速排序之因此快是由於:它每次選定軸值pivot並進行劃分子集(分割交換)後該軸值被一次性的放到了他最終該放到的位置。數組
下標函數 |
0性能 |
1ui |
2spa |
3指針 |
4code |
5對象 |
6 |
7 |
初始 |
25 |
34 |
45 |
32 |
34` |
12 |
29 |
64 |
選基準 |
25 |
34 |
45 |
29 |
34` |
12 |
32 |
64 |
分割 |
25 |
12 |
45 |
29 |
34` |
34 |
32 |
64 |
分割 |
25 |
12 |
29 |
45 |
34` |
34 |
32 |
64 |
基準定位 |
25 |
12 |
29 |
32 最終位置 |
34` |
34 |
45 |
64 |
//#pragma once //QuickSort.h #include <iostream> using namespace std; const int Cutoff = 28; //閾值,當子序列元素個數小於Cutoff時,採用簡單排序 template <class T> class Quick { private: T * A; //用來存儲待排序列的數組 int N; //待排序列元素個數 public: Quick(int size); //構造函數 ~Quick() { delete[] A; } //析構函數 void QuickSort(int Left, int Right); //遞歸進行快排 T Median3(int Left, int Right); //選主原(軸值)- 取頭、中、尾的中位數 friend void Swap(T* a, T* b); //交換兩個數 - 友元函數 void InsertSort(T* B, int Nb); //當子序列元素個數小於閾值時調用插入排序 void Print(); //輸出結果 }; //Quick類的實現 //構造函數初始化 template <class T> Quick<T>::Quick(int size) { N = size; A = new T[N]; for (int i = 0; i < N; i++) cin >> A[i]; } //交換兩個數 template <class T> Swap(T* a, T* b) { int tmp; tmp = *a; *a = *b; *b = tmp; } //輸出結果 template <class T> void Quick<T>::Print() { for (int i = 0; i < N; ++i) { cout << A[i] << " "; } } //插入排序 template <class T> void Quick<T>::InsertSort(T* B, int Nb) { int tmp, p, i; for (p = 1; p < Nb; ++p) //總共摸取Nb-1張牌 { tmp = B[p]; //當前摸到手中的一張牌 for (i = p; i > 0 && A[i - 1] > tmp; i--) //i不少狀況下都是用來控制循環次數的 { A[i] = A[i - 1]; } A[i] = tmp; //新牌歸位 } } //選軸值pivot template <class T> T Quick<T>::Median3(int Left, int Right) { int Center = (Left + Right) / 2; if (A[Left] > A[Center]) Swap(&A[Left], &A[Center]); if (A[Left] > A[Right]) Swap(&A[Left], &A[Right]); if (A[Center] > A[Right]) Swap(&A[Center], &A[Right]); //此時A[Left] <= A[Center] <= A[Right],爲了接下來的分割過程,將軸值藏到右邊 //將軸值藏到子序列的右端只是爲了避免影響分割過程 //分割時只需考慮A[Left+1] - A[Right-2]的區間 Swap(&A[Center], &A[Right - 1]); //返回軸值 return A[Right - 1]; } //遞歸分割 template <class T> void Quick<T>::QuickSort(int Left, int Right) { int Pivot, Low, High; //基準、左、右指針 if (Cutoff < Right - Left) //若是序列元素充分多,則進入快排 { Pivot = Median3(Left, Right); Low = Left; High = Right - 1; //分割過程 while (true) { while (A[++Low] < Pivot); while (A[--High] > Pivot); if (Low < High) Swap(&A[Low], &A[High]); else break; } //將當前子序列的軸值一次性的放到他最終所在的位置上 - Low Swap(&A[Low], &A[Right - 1]); //當前子序列分割完成,遞歸進入更小一層子序列的分割 QuickSort(Left, Low - 1); //遞歸解決左邊子序列 QuickSort(Low + 1, Right); //遞歸解決右邊子序列 } else InsertSort(A + Left, Right - Left + 1); //當子序列足夠短時,採用插入排序 } int main() { int N; //待排元素個數 cin >> N; //定義Quick對象QuickA Quick<int> QuickA(N); //快速排序 QuickA.QuickSort(0, N - 1); //輸出結果 QuickA.Print(); return 0; }