在不同的STL实现中,C ++ 11 std :: sort中使用了哪些算法?

时间:2014-03-11 23:58:32

标签: c++ algorithm sorting c++11 stl

C ++ 11标准保证std::sort在最坏的情况下O(n logn) complexity 。这与C ++ 98/03中的 average-case 保证不同,其中std::sort可以使用Quicksort实现(可能与小n的插入排序结合使用),其中包含O( n ^ 2)在最坏的情况下(对于某些特定的输入,例如排序的输入)。

不同STL库中的std::sort实现是否有任何变化? C ++ 11的std::sort如何在不同的STL中实现?

2 个答案:

答案 0 :(得分:24)

问题是, STL 如何说std::sort最坏情况是 O(N log(N)),即使它本质上是<强>快速排序即可。 STL的排序是 IntroSort 。 IntroSort本质上是一个QuickSort,引入的差异改变了最坏的情况复杂性。


QuickSort最坏情况是O(N ^ 2)

您选择的分区中,存在QuickSort将在 O(N ^ 2)上运行的序列。您选择的分区只会降低最坏情况发生的概率。 (Random Pivot Selection,三人中位数,etc.

编辑:感谢@ maxim1000的更正。具有数据透视选择算法Median of Medians的Quicksort具有 O(N log(N))最差情况的复杂性,但由于其引入的开销,它在实践中未被使用。它显示了良好的选择算法,从理论上可以通过枢轴选择改变最坏情况的复杂性。


IntroSort做什么?

IntroSort限制了QuickSort的分支。这是最重要的一点,该限制为 2 * (log N)。达到限制时,IntroSort可以使用任何具有最差情况复杂度O(N log(N))的排序算法。

当我们有O(log N)子问题时,分支停止。我们可以解决每个子问题O(n log n)。 (小写字母n代表子问题大小)。

现在,(n log n)的总和是我们最糟糕的情况。

对于最糟糕的QuickSort案例;假设我们已经有一个已排序的数组,我们总是选择此数组中的第一个元素作为数据透视表。在每次迭代中,我们只消除第一个元素。如果我们这样走到最后,那么显然会 O(N ^ 2)。使用IntroSort我们停止QuickSort,当我们达到深度 log(N)时,我们使用 HeapSort 来保留剩余的未排序数组。

16 -> 1  /**N**/
   \
    > 15 -> 1 /**N - 1**/
         \
          > 14 -> 1 /**N - 2**/
               \
                > 13 -> 1 /**N - log(N)**/  
                     \
                      > 12 /**(HeapSort Now) (N - log(N)) log (N - log(N))**/

总结一下;

在分支停止之前,N + (N - 1) + ... + (N - log(N))操作已完成。我们可以简单地说N + (N - 1) + ... + (N - log(N)) < N log(N)

,而不是使用高斯来总结

HeapSort部分是(N - log(N)) log(N - log(N)) < N log(N)

整体复杂性< 2 N log(N)

由于常数可以省略, IntroSort 的最坏情况复杂度为 O(N log(N))


已添加信息 GCC STL实施源代码为hereSort功能位于 5461

更正: * Microsoft .NET * sort自2012年起,实施就是IntroSort。相关信息是here

答案 1 :(得分:19)

浏览libstdc++libc++的在线资源,可以看到两个图书馆都使用了来自intro-sort主循环的众所周知的排序算法:

对于std::sortinsertion_sort有一个辅助例程(一个O(N^2)算法,但具有良好的缩放常数以使其对小序列具有竞争力),加上一些特殊的子套管 - 0,1,2和3个元素的序列。

对于std::partial_sort,两个库都使用heap_sort版本(通常为O(N log N)),因为该方法具有良好的不变性,可以保留已排序的子序列(通常具有较大的子序列)缩放常数使其对于完全排序更加昂贵)。

对于std::nth_elementselection_sort有一个辅助例程(同样是一个具有良好sclaing常数的O(N ^ 2)算法,以使其与小序列竞争)。对于常规排序insertion_sort通常支配selection_sort,但对于nth_element,具有最小元素的不变量与selection_sort的行为完全匹配。