C ++中的sort()有n ^ 2的性能吗?

时间:2011-06-03 16:54:42

标签: c++ algorithm sorting gnu

在尝试估计程序的性能时,我总是将sort()函数视为性能最差的n ^ 2函数。但是,我遇到了一个维基百科页面:

sort(C++)

其中说GNU C Library sort()首先使用一些名为Introsort的混合排序算法,然后进行插入排序。 Introsort的相应页面声称该算法具有nlogn的最差情况。但是,由于我不熟悉这个算法,我仍然担心sort():

1)GNU sort()使用的混合算法能否保证O(nlogn)性能?如果是这样,nlogn的持续开销有多大?

2)是否有任何其他实现可能导致sort()执行比这更差(或更好,这会很棒)?

编辑:回复Kevin:提到的sort()是std :: sort()。

谢谢!

5 个答案:

答案 0 :(得分:5)

使用quicksort和introsort(这是前者的变体,通过在最坏情况输入时切换到heapsort来实现保证O(n log n)性能)代替其他理论上更好的算法,例如mergesort,这是由于事实平均情况是相同的,并且常量要低得多(在常量中你可以包括它可以在适当位置排序的事实,因此没有重新分配和副本)。而最糟糕的情况是坏的,但很容易改进。通常,假设sort的效果为O( n log n )

如果你担心隐藏的常数,那么问题不是理论问题,而是性能问题。在尝试优化时,最好在实际数据上测量算法,分析测量结果,然后确定花费的时间以及是否可以改进。但这与理论问题完全不同。

答案 1 :(得分:3)

如果您的标准库不能保证超出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 - sort [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. 效果:对[first,last]范围内的元素进行排序。

  2.   
  3. 复杂性:大约N log N(其中N == last-first)平均比较。*

  4.         

    [脚注:如果最坏的情况是重要的,应该使用stable_sort()(lib.stable.sort)或partial_sort()(lib.partial.sort)。 ---结束脚注]

特定的库实现可能会提供超出标准的更强保证。直接查看代码肯定是有用的。再说一次,这取决于你想要的便携性。

答案 2 :(得分:2)

Introsort实际上有O(n log(n))最坏情况下的运行时间,而不是O(n ^ 2)。 另请参阅SGI STL规范中的this remark

  

早期版本的排序使用了   快速排序算法,使用数据透视表   按中位数选择三个。快速排序   具有O(N log(N))平均复杂度,   但是二次最坏情况的复杂性。   但是,sort的当前实现使用了introsort   算法的算法   最坏情况的复杂性是O(N log(N))。   Introsort非常相似   三分之一的快速排序,现在是   至少和平均快速排序一样快。

答案 3 :(得分:1)

是的,它是快速排序的变体,使用heapsort进行可疑的病态快速输入输入。它着眼于递归深度,当它下降得太深时,它会使用heapsort去除任何病理行为。这保证了N log N.N log N(qsort vs heapsort)的恒定开销不用担心。

当元素很少(约16个)时使用插入排序。

答案 4 :(得分:0)

http://en.wikipedia.org/wiki/Sorting_algorithm列出了几种具有n ^ 2性能的排序算法。它有一个与n!性能。它还列出了几种基于其他因素具有性能的非比较排序。