使用C++實現快速排序QuickSort
阿新 • • 發佈:2019-02-15
參考了weiss的《資料結構與演算法分析》的C++描述第三版。
快速排序原理其實很簡單,是一個遞迴的過程。首先確定一個樞紐元,然後把大於樞紐元的元素放在左邊,把小於樞紐元的元素放在右邊。然後再對左右兩邊的子序列不斷的重複這個操作(確定樞紐元,然後把大小元素歸類),直到子序列中的元素為0個或1個的時候結束。
需要注意的兩個地方:第一個是樞紐元的選取。最好不要直接選擇序列的第一個元素作為樞紐元,因為在待排序列較為有序的時候,可能會一直處於最壞的情形。常見的選取方法是三數取中(詳細的可見下面的程式)。
第二個需要注意的地方是如何處理等於樞紐元的元素。對於從兩邊往中間走的遊標i和j來說,如果遇到等於樞紐元的元素,就應該讓i和j停止。
程式如下:
#include<iostream> #include<vector> #include<random> #include<ctime> #include<iterator> #include<algorithm> using namespace std; /* * 快速排序通過遞迴實現,因此該函式為驅動函式 */ template<typename Comparable> void quickSort(vector<Comparable> & a) { quickSort(a, 0, a.size() - 1); } /* * 通過“三數選中”的方法選擇樞紐元 * 找到樞紐元后,放在right-1的位置上 */ template<typename Comparable> const Comparable & median3(vector<Comparable> &a, int left, int right) { //從對left,center,right位置上的三個數進行排序 int center = (left + right) / 2; if (a[center] < a[left]) swap(a[left], a[center]); if (a[right] < a[left]) swap(a[right], a[left]); if (a[right] < a[center]) swap(a[right], a[center]); //此時left、center、right位置上的數從小到大排序,且center位置上的元素為樞紐元 //現在把center上的樞紐元放在right-1 的位置上 swap(a[center], a[right - 1]); return a[right - 1]; } /* 快速排序主要的函式 a表示待排的向量 left表示子序列的最左邊元素下標 right表示子序列的最右邊元素的下標 */ template<typename Comparable> void quickSort(vector<Comparable> & a, int left, int right) { if (left + 10 < right) { Comparable pivot = median3(a, left, right); int i = left; int j = right - 1; while (1) { while (a[++i] < pivot); while (a[--j] > pivot); //因為如果i和j遇到等於樞紐元的元素,就讓i和j都停止 if (i < j) swap(a[i], a[j]); else break; } swap(a[i], a[right - 1]);//把樞紐元放回在相應的位置 quickSort(a, left, i - 1);//把小於樞紐元的集合排序 quickSort(a, i + 1, right);//把大於樞紐元的集合排序 } else { insertionSort(a, left, right); } } /* 在快速排序遞迴的時候,如果向量長度小於10就用插入排序 */ template<typename Comparable> void insertionSort(vector<Comparable> & a, int left, int right) { for (int p = left + 1; p <= right; ++p) // 從第二個數開始 { Comparable tmp = a[p]; int j = p; for (; j > left && a[j - 1] > tmp; --j) a[j] = a[j - 1]; a[j] = tmp; } } /*輸出向量*/ template<typename T> void printVector(vector<T> & v) { copy(v.cbegin(), v.cend(), ostream_iterator<T>(cout, " ")); cout << endl; } int main() { vector<int> source; uniform_int_distribution<int> u(0, 10); default_random_engine e(static_cast<unsigned int>(time(0))); for (int i = 0; i < 31; i++) { source.push_back(u(e)); } cout << "排序前:" << endl; printVector(source); quickSort(source); cout << "排序後:" << endl; printVector(source); return 0; }
結果如圖(以含有多個相同元素的序列為例)