参考了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;
}
结果如图(以含有多个相同元素的序列为例)