C++中的Can sort()具有n^2的性能

Can sort() in C++ have a n^2 performance?

本文关键字:性能 具有 中的 Can sort C++      更新时间:2023-10-16

当试图估计程序的性能时,我总是将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)
  1. 效果:对范围内的元素进行排序[第一个,最后一个)。

  2. 复杂度:平均约为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!表演它还列出了几种非比较排序,它们的性能基于其他因素。