时间测试 这将我们置身何处?我已经对时间作了一些论断,而且我们还能作些更直觉的预测:比如, 在set中插入一个元素将比排序一个vector慢,因为set是一个复杂的数据结构,它需要 使用动态内存分配;或者,排序一个list应该和使用stable_sort差不多快,它们都是归 并排序的变种。然而,直觉不能取代时间测试。测量很困难 (更精确地说,你要测量什么, 又如何测量?),但这是有必要的。 Listing 1的程序构造了一个vector ,其中的元素乱序排列,然后用我们讨 论过的每个方法(除了qsort()(WQ注:原文如此))反复对它进行排序。在将vector传给 每个测试用例时,我们故意使用传值:我们不想让任何一个测试用例得到一个已排序的vector! 用Microsoft Visual C++ 7 beta编译程序(结果和g++相似),在500M的Pentium 3上进行, 结果如下: Sorting a vector of 700000 doubles. sorting method t (sec) sort 0.971 qsort 1.732 stable_sort 1.402 heap sort 1.282 list sort 1.993 set sort 3.194 这和期望相符:sort()最快;stable_sort()、堆排序和qsort()稍慢;排序一个list 和set(它使用动态内存分配,并且是个复杂的数据结构),更加慢。 (实际上,qsort()有一 个不寻常的好成绩:在g++和VC的老版本上,qsort()仅比sort()慢。) 但这不足以称为排序基准测试--太不具有说服力了。我在一个特定的系统上,使用一个 特定的(乱序)初始化,来测试排序一个vector 。只有实践能决定这些结果有多大 的普遍性。至少,我们应该在double以外再作些测试。 Listing 2排序一个vector :它打开一个文件并将每一行拷贝进一个独立的string。 因为qsort()不能处理具有构造函数的元素,所以这个测试中不再包括qsort()。以Project Gutenberg的免费电子文本《Anna Karenina》[注4]作为输入,结果是: Sorting a file of 42731 lines. sorting method t (sec) sort 0.431 stable_sort 1.322 heap sort 0.751 list sort 0.25 set sort 0.43 突然之间,事情发生了变化。我们仍然看到sort()比stable_sort()和堆排序快得多, 但list和set的结果发生了戏剧性的变化。使用set的速度几乎和sort()一样,而list实际 上更快。发生了什么? 变化是double是原生类型,而std::sting是一个复杂的class。拷贝一个string或将 它赋值给另一个,意味着要调用一个函数--甚至意味着需要使用动态内存分配或创建一个 mutex锁。平衡点被改变了;排序string比排序double时,赋值的次数将有更多的影响。 排序一个list时,根本没有调用赋值运算:定义一个特别的list::sort()成员函数的全部 理由就是它通过操纵指向list的内部节点的指针来工作的。重连接一些list的node的指针 比拷贝一个string快。 我们再度发现一个老的至理名言:如果你正在处理大的记录,你绝不要排序记录本身, 排序指向它们的指针。使用list使得这一点成为自动,但你也能很容易地显式做到这一点: 不是排序原始的vector ,取而代之,创建一个索引vector,其元素类型是vector ::const_iterator,然后排序这个索引vector。你必须告诉sort()如 何比较索引vector的元素(你必须确保比较的是iterator所指的值而不是iterator本身), 不过这只是个小问题。我们只需提供一个合适的比较函数对象: template struct indirect_lt { bool operator()(Iterator x, Iterator y) const { return *x < *y; } }; Listing 3展示了如何使用indirect_lt,并对比了直接排序和间接排序时的速度。 速度的提升是显著的。 Sorting a file of 42731 lines. sorting method t (sec) indirect sort 0.29 sort 0.401 建议 标准C++运行库提供了六个排序方法:qsort(),sort(),stable_sort(), partial_sort(),lsit::sort(),和set/multiset。 你不应该在新代码中使用qsort()。它比sort()慢。它的接口丑陋,因为它需要 类型转换,并易于用错。写一个比较函数以传给qsort()可能很麻烦,尤其是在泛型 代码中。你不能使用qsort()排序有构造函数或虚函数的东西,或排序C语言的数组以 外的任何数据结构。虽然qsort()没有正式说不推荐使用,但它唯一真正的用处是对C 语言的向后兼容。 在其它五个排序方法中,前三个是泛型算法,后两个则使用了某些容器的特别特性。 所有这些方法默认都使用operator<()来比较对象,但允许在必要时指定用户自己的比 较函数。每个都提供了一些特别的特征: l sort()通常最快。 l stable_sort()保证了等价元素在顺序上的稳定。 l partial_sort()允许只排序出前N个元素。 l list::sort()操纵指针,而不是拷贝元素。 l set允许在一个已序区间快速的插入和删除 如果你不需要其它四个方法的特别特征,首选通常应该是sort()。
STL排序比
最新推荐文章于 2022-04-09 18:04:27 发布