stl

Quick sort(快速排序)杂谈 3

在上一篇我们介绍了快排的各种优化,最后得到了一个超越VS的STL std::sort实现的版本,这回我们来讲讲怎么折磨gcc的std::sort。 GCC的实现 这个我直接给个github来源,链接里是gcc8分支的实现源码,我已经通过链接标记出第1896行,那里就是__unguarded_partition函数的实现,就是快排的划分函数,而在后面几个函数就是快排的本体了。为了避免它代码更新导致位置变化,我把相关代码复制过来。

Quick sort(快速排序)杂谈 2

在上一篇我们介绍了四种不同的划分算法,现在我们来针对Hoare partition scheme来讲解一些优化和注意的问题。 最坏时间复杂度的优化 在前一篇的示例代码里面,只是最简单地选择的最开头或最后面的元素作为划分,这对于乱序的数据还好,对于有序的数据这么做,时间复杂度就直接变成$O(n^2)$了,那么怎么解决?第一个要解决的反而不是划分元素的选择上,而是改成intro sort,记录递归深度或类似的办法,到达限制条件的时候改而使用堆排序,这属于混合排序,先让排序的最坏时间复杂度降下来是第一要务。所以可以改写出以下代码:

Mingw 的 Bug

这个问题最早的时候是今年8月,我在测试排序算法的速度,发现mingw上总有点不一样,而linux下的gcc是正常的,也在群里问过人,没人明白到底怎么回事,先描述一下当时遇到的情况。 一开始我使用std::random_shuffle打乱数组并用std::sort排序,在VS上并没有发现什么问题,gcc也正常。但在mingw上,这样打乱的数组排序所花的时间,比起其它打乱方式的,例如直接赋值一个随机数的方式,要明显慢了近1倍,这个诡异的问题一直没想通是为啥。当时觉得可能是std::sort对这种方式打乱的数据排序有点问题导致变慢。 后来,为了和std函数脱钩,我自己重新写了随机数函数和random_shuffle函数,结果发现我的random_shuffle函数打乱的结果,std::sort的时间是完全正常的,非得std::random_shuffle才会出现两倍的情况,一时间我还以为是我写的有问题,还更换了不同随机函数,怎么也发现不了原因,终于把怀疑转向std::random_shuffle,我就对这个函数的执行结果输出到文件,这一输出立即把我搞懵了,输出的结果分布特别有规律,初值我用的是arr[i] = i,打乱后结果前32768个数都是数组里最大的数值,一时没明白怎么回事,难道它的实现很不寻常吗?我就去翻了一下源代码,在cppreference下源代码长下面这样: