SGI的STL中的sort算法并不是普通的快排,而是对快排改进后的内省排序。优化的地方有检测快排是否发生分割恶化,若分割次数超出预期值则改为堆排。另一个优化是快排只负责大范围的排序,对于小序列(比如长度小于16的数组)则停止排序,减少小序列排序产生的多次函数递归调用。小序列的排序最后则由插入排序完成。STL的sort的入参是两个随机迭代器,这也体现了迭代器在容器和算法之间的粘合剂的作用。注意快排需要比较前向指针是否小于后项指针,因此只支持随机迭代器。下边的排序则使用模板函数实现快排。对于int,char,double类型均进行了测试。
#include <vector>
#include <iostream>
#include <string>
using namespace std;
vector<int> a = {9,4,2,7,5,6,0,1,3,10,14,8,11,15,18,19,17,16,12,13};
double b[20] = { 0.0, 4.4, 2.2, 7.7, 5.5, 6.6, 9.9, 1.1, 3.3, 10, 14, 8, 11, 15, 18, 19, 17, 16, 12, 13 };
char c[20] = { 'a', 's', 'd', 'f', 'g','h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'q', 'w', 'e', 'r' };
template <typename Randomaccessiterator>
Randomaccessiterator partition(Randomaccessiterator first, Randomaccessiterator last)
{
auto pirvot = *first;
while (first<last)
{
while (first<last&&(*last >pirvot)) --last;
*first = *last;
while (first<last && (*first < pirvot)) ++first;
*last = *first;
}
*first = pirvot;
return first;
}
template <typename Randomaccessiterator>
void qsort(Randomaccessiterator start, Randomaccessiterator end)
{
if (start < end)
{
auto pivotpos = partition(start, end);
if (!(pivotpos == start)) //此句不可少,原始指针可以没有这句,但是迭代器没有这句会内存溢出
qsort(start,pivotpos-1);
if (!(pivotpos == end))
qsort(pivotpos + 1,end);
}
}
int main(int argv, char** argc)
{
cout << "排序前: ";
for (auto i = a.begin(); i!=a.end(); ++i)
cout << *i << " ";
cout << endl << "排序后: ";
qsort(a.begin(),--a.end()); //整形
for (auto i = a.begin(); i != a.end(); ++i)
cout << *i << " ";
cout << endl;
cout << "排序前: ";
for (int i = 0; i < 20; ++i)
cout << b[i] << " ";
cout << endl << "排序后: ";
qsort(b,b+19); //浮点
for (int i = 0; i < 20; ++i)
cout << b[i] << " ";
cout << endl;
cout << "排序前: ";
for (int i = 0; i < 20; ++i)
cout << c[i] << " ";
cout << endl << "排序后: ";
qsort(c,c+19); //字符
for (int i = 0; i < 20; ++i)
cout << c[i] << " ";
cout << endl;
}
测试结果: