根据effective STL中Item 46 提到, C程序员很难接受C++的STL中std::sort(定义于头文件<algorithm>)竟然比C语言的std::qsort(定义与头文件<cstdlib>中)快了670%。 最后Scot Meyer建议我们我们要使用C++的std::sort函数。
我们知道qsort 实现的排序算法是快排, 但是std::sort 实现的排序算法并不知道, 有人说这得看是哪一个STL版本了。 std::sort的大部分实现的是quick sort(也是快排), 或者是一个类似于插入排序的, 结合了快排, 堆排, 以及插入排序的混合算法。 总而言之,sort和qsort的算法复杂度是O(nlogn)。
但是, std::sort更快。 快的原因是运行的时候, sort函数使用inline的方式调用比较函数(comparision function), 然而qsort使用的是指针的方式调用(即function pointer)comparison function。 Meyer称, sort通过使用comparing funcion object(即functor) 作为算法的参数, 使得排序的时间大大降低, 这是一个"abstraction bonus"。
为了体现个算法性能差别, 我们对size很大的数组(大小为10000000(一千万个随机数))排序。测试函数如下:
#include <iostream> #include <vector> #include <algorithm> #include <cstdlib> // for rand() function #include <ctime> // #include <cstdio> const size_t LARGE_SIZE = 1000000; // functor struct rnd { int operator()() { // overloading () return rand() % LARGE_SIZE; // rand() returns range between 0 and RAND_MAX } }; int comp( const void* a, const void* b ) { return ( *( int* )a - *( int* )b ); // casting and then minus, return 0 if equals } int main() { int ary[LARGE_SIZE]; int ary_copy[LARGE_SIZE]; // generate random data std::generate( ary, ary + LARGE_SIZE, rnd() ); std::copy( ary, ary + LARGE_SIZE, ary_copy ); // get time std::time_t start0 = std::clock(); // perform quick sort C using function pointer std::qsort( ary, LARGE_SIZE, sizeof( int ), comp ); std::time_t end0 = std::clock(); std::cout << "C quick-sort time elapsed: " << static_cast<double>( end0 - start0 ) / CLOCKS_PER_SEC << "\n"; // get time again std::time_t start1 = std::clock(); // perform quick sort C++ using function object std::sort( ary_copy, ary_copy + LARGE_SIZE ); std::time_t end1 = std::clock(); std::cout << "C++ quick-sort time elapsed: " << static_cast<double>( end1 - start1 ) / CLOCKS_PER_SEC << "\n"; }
为了运行该程序, 需要注意一下几点。 NOTE:
(1)由于数组为一千万个int, 占用的栈内存4 * 10MB即40MB的内存, 而一般的compiler的能够分配的栈内存只是1MB, 显然尽管能通过编译, 但是运行的时候, 程序会crashed。 所以我我们需要重新设置stack size。 我使用的IDE是code::blocks, 使用的编译器是Mingw, 我亲自测试了一下, 内存大小栈内存大小仅为1 M 左右, 测试程序如下:
#include <cmath> #include <iostream> using namespace std; int main(void) { const int n = pow(2,20); // 指数超过20, 程序就crashed char arr[n]; // size(arr) = 1MB return 0; }
扩大占内存的办法如下:
settiings -> compiler -> linker settings , 然后在other linker options 下面打入如下指令:
-Wl,--stack=100000000
意思是我们将栈的size设置为100MB, 当然可以处理1千万个整数(40MB). 如下图:
ok 即可大功告成。
(2)wait wait, 还要注意一个事情, 就是我们必须release的mode 下面编译, 而不是在debug模式下面进行编译运行。
因为 release mode确保you compiled with all optimizations. 否则会出错, 我在debug 下面测试一些, 结果是qsort会快些, 显示是没有用到abstraction
bonus啊。
注意: Debug通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用.
注意, 下图选择release mode。
接下来开始测试。。。, 如下图:
说明C++中的std::sort更快。