C++中的Can sort()具有n^2的性能
Can sort() in C++ have a n^2 performance?
当试图估计程序的性能时,我总是将sort()函数视为性能较差的n-^2函数。然而,我看到了一个维基百科页面:
排序(C++)
声明GNU C Library sort()首先使用了一种名为Introsort的混合排序算法,然后进行插入排序。Introsort对应的页面声称该算法的性能最差。然而,由于我不熟悉这个算法,我仍然对sort()有以下担忧:
1) GNU sort()使用的混合算法能保证O(nlogn)性能吗?如果是,nlogn的恒定开销可以有多大?
2) 有没有其他实现会导致sort()的性能比这更差(或者更好,这会很好)?
编辑:回复Kevin:提到的排序()是std::sort()。
谢谢!
使用quicksort和introsort(这是前者的变体,通过在最坏情况下切换到heapsort来保证O(n log n)
性能)来代替其他理论上更好的算法,如mergesort,是因为平均情况是相同的,常数要低得多(在常数中,您可以包括这样一个事实,即它可以在适当的位置排序,因此没有重新分配和复制)。最坏的情况是糟糕的,但可以改进。通常,假设sort
的性能为O( n log n )
。
如果你关心隐藏的常数,那么问题不是理论上的,而是性能问题。在尝试优化时,最好根据实际数据测量算法,分析测量结果,然后确定时间花在哪里以及是否可以改进。但这是一个与理论问题完全不同的问题。
如果您的标准库在ISO 14882之外没有任何保证,那么sort()
的最坏情况似乎没有正式的约束;只列出了平均复杂度。标准中有一个脚注提到,如果你愿意,你应该使用stable_sort()
或partial_sort()
而不是sort()
:
http://www.kuzbass.ru:8086/docs/isocpp/lib-algorithms.html#lib.alg.sorting
25.3.1.1-排序[lib.sort]
template<class RandomAccessIterator> void sort(RandomAccessIterator first, RandomAccessIterator last) template<class RandomAccessIterator, class Compare> void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
效果:对范围内的元素进行排序[第一个,最后一个)。
复杂度:平均约为N log N(其中N==倒数第一)比较。*
[脚注:如果最坏情况的行为是重要的,则应使用stable_sort()(lib.stable.sort)或partial_sort((lib.partial.sort)。---结束脚注]
特定的库实现可能会在标准之外提供更强的保证。直接查看代码肯定会很有用。再说一遍,这取决于您希望它的可移植性。
Introsort实际上有O(n-log(n))最坏情况下的运行时间,而不是O(n^2)。另请参阅SGI STL规范:上的备注
早期版本的排序使用使用pivot的快速排序算法由三的中位数选择。快速排序具有O(N log(N))的平均复杂度,而是二次型最坏情况复杂度。然而,sort的当前实现使用introsort算法最坏情况的复杂性是O(N log(N))。Introsort与三个快速排序的中值,并且位于平均速度不如快速排序。
是的,它是quicksort的变体,对可疑的病理性quicksort输入使用heapsort。它关注递归深度,当递归深度太深时,它会使用heapsort进行排序,删除任何病理行为。这保证了N log N。N log N的恒定开销(qsort vs heapsort)不需要担心。
当元素非常少(大约16个)时,使用插入排序。
http://en.wikipedia.org/wiki/Sorting_algorithm列出了几种性能为n^2的排序算法。它有一个n!表演它还列出了几种非比较排序,它们的性能基于其他因素。
- 在现代C++中,侵入式容器是否仍然比非侵入式容器具有性能优势?
- 使用C STL StringStream记录具有实时性能要求
- 具有周期检测的呼叫研磨性能分析
- 虚拟继承的性能开销(如果只有一个基具有数据成员)
- 为什么在某些特定情况下具有多个线程(并行处理)会降低性能
- 具有预定义容量的C++矢量性能
- 具有良好性能的c++映射实现
- C 具有数学库,例如GSL,Lapack或CBLAS性能与带有R函数的Rinside的C .态
- 一
- C++-静态数组的性能,在启动时具有可变大小
- 具有任意基数的基本任意精度算术的最佳性能
- 具有相同索引的循环的性能
- 为什么我的代码在不同的环境中具有OpenMP性能不同
- 为什么具有多线程的for循环的性能不如单线程
- 具有不同类型的按位移位表达式 1 <<表达式 2 会损害性能吗?
- 具有 *派生* 类中的函数的虚拟关键字对性能的影响
- 将两个C++类封装到一个具有性能注意事项的高级类中
- 哪个性能更快?具有 N 个派生类型的 vtable 查找,或具有 N 个元素的 std::map 查找
- 为什么具有多个后缓冲区对性能更好
- C++具有继承类的奇怪性能
- 具有许多C++互操作调用的自动C#垃圾回收器性能较差