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

C++ C+中使用了哪些算法+;11 std::在不同的STL实现中排序?,c++,algorithm,sorting,c++11,stl,C++,Algorithm,Sorting,C++11,Stl,C++11标准保证std::sort在最坏的情况下具有。这与C++98/03中的平均情况保证不同,在C++98/03中,std::sort可以通过快速排序(可能与小n的插入排序相结合)实现,在最坏的情况下(对于某些特定输入,例如排序输入),插入排序有O(n^2) 不同STL库中的std::sort实现是否有任何变化?C++11的std::sort是如何在不同的STL中实现的?浏览和的在线源代码,可以看到两个库都使用了intro-sort主循环中的所有著名排序算法: 对于std::sort,有一个

C++11标准保证
std::sort
在最坏的情况下具有。这与C++98/03中的平均情况保证不同,在C++98/03中,
std::sort
可以通过快速排序(可能与小n的插入排序相结合)实现,在最坏的情况下(对于某些特定输入,例如排序输入),插入排序有O(n^2)


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

浏览和的在线源代码,可以看到两个库都使用了intro-sort主循环中的所有著名排序算法:

对于
std::sort
,有一个用于
insertion\u sort
的辅助例程(一个
O(N^2)
算法,但具有良好的缩放常数,使其对小序列具有竞争力),另外还有一些用于0、1、2和3个元素的子序列的特殊外壳

对于
std::partial_sort
,这两个库都使用
heap_sort
O(N log N)
)的一个版本,因为该方法有一个很好的不变量,它保持了一个排序后的子序列(它通常有一个更大的缩放常数,使完全排序的成本更高)

对于
std::N_元素
,有一个用于
选择_排序
的辅助程序例程(同样是一个O(N^2)算法,该算法具有良好的sclaing常量,使其对小序列具有竞争力)。对于常规排序,插入排序通常占主导地位,但对于第N个元素,最小元素的不变量与选择排序的行为完全匹配。问题是,STL如何说std::sort最坏的情况是O(N log(N))
,尽管它本质上是一种快速排序。STL的排序是内部排序。IntroSort本质上是一种快速排序,引入的差异改变了最坏情况下的复杂性


快速排序最坏的情况是O(N^2) 无论您选择什么分区,都存在一个序列,QuickSort将在O(N^2)上运行。您选择的分区只会降低最坏情况发生的概率。(,中位数为三,)

编辑:感谢@Maxims 1000的更正。带有枢轴选择算法的快速排序具有O(N log(N))最坏情况的复杂性,但由于它引入的开销,它没有在实践中使用。它从理论上说明了好的选择算法如何通过枢轴选择改变最坏情况的复杂性


IntroSort做什么? IntroSort限制了快速排序的分支。这是最重要的一点,限制为2*(对数N)。当达到限制时,IntroSort可以使用最坏情况复杂度为O(N log(N))的任何排序算法

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

现在,(n logn)之和是最坏情况的复杂性

对于最坏的快速排序情况;假设我们有一个已经排序的数组,我们总是选择这个数组中的第一个元素作为轴心。在每次迭代中,我们只去掉第一个元素。如果我们沿着这条路走到最后,它显然是O(N^2)。使用IntroSort,我们停止快速排序,当我们到达深度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-记录(N))
操作已完成。我们可以简单地说,
N+(N-1)+…+而不是用高斯求和(N-log(N))

堆头部分是
(N-log(N))log(N-log(N))

总体复杂性
<2N日志(N)

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


添加信息:GCCSTL实现源代码为<代码>排序
功能位于第5461行


更正:*自2012年起,Microsoft.NET*排序实施开始引入排序。相关信息是。

这不是一个正确的答案,因为我还没有进行全面的调查,但基本上每个人都已经在使用Introsort了,这就是为什么更强的需求实际上对实现者来说不是问题。甚至在Introsort之前,没有人使用以最左边的元素为轴心的快速排序。为了演示该算法,这是一种简化,尽管它对随机数据也确实很有效。所以在实践中,快速排序最糟糕的情况不是排序输入。是的,混合快速排序(如introsort)几乎是每个人都使用的。我想你也可以找到像timsort这样的合并排序混合体。如果你试图评估排序方法,请检查排序过程中创建的构造函数的数量。如果默认构造函数效率低下,那么无论排序速度有多快,它都会很慢。@bamboon它不是重复的,因为它吸引了对C++11标准中std::sort的强化要求的注意。真正的问题是:C++11 std::sort实现是否符合C++11标准O(n logn)最坏情况的要求?(在前面提到的答案中,提到了std::sort的O(n^2)最坏情况复杂性,现在不可能了。)@cup您指的是复制构造函数(假设没有移动构造函数,也没有快速专门化
std::swap
),我想?我根本不明白为什么要调用默认构造函数。问题有点不同——现在在各种STL实现中如何实现std::sort——是不是