今天面试被问到了快排与堆排的应用场景,思考了一下只答上来了数据基本有序的情况下堆排优于快排以及topK问题选择堆排,更进一步却答不上来。
后来发现其实堆排序和快速排序平均复杂度虽然都是O(NlogN)但是在最差情况下堆排复杂度也是O(NlogN)这一点比快排要好。但是稍微实验一下就能发现,堆排序虽然平均复杂度和快排是一样的,但是它平均交换元素次数是要比快排高出很多的,所以虽然时间开销都是NlogN但是堆排序的常数要大出不少,所以在元素基本无续的情况下快排速度还是会快一些。
还有就是在数据量逐渐增大的情况下,堆排序的交换元素次数随着数据量的增大而增大,所以性能开销也会越来越大,跟快速排序的差距就慢慢拉开了。所以在数据量较大的情况下选择快速排序是一个比较正确的选择。
这里不得不提一下stl算法中的std::sort这个排序函数了。这个标准库的排序算法还是十分高效的,底层实现是插入排序 + 快排 + 堆排。
首先讲一下为什么插入排序平均时间复杂度为O(N^2)的排序算法也能上榜吧。
插入排序:
插入排序虽然平均时间复杂度不是很乐观,但是在元素基本有序的情况下它的时间复杂度是接近O(N)的
快速排序:
我们都知道快速排序是基于分治的思想,需要通过递归来实现。当分段很小的情况下,快速排序还需要进行递归来交换数据,而递归需要将函数压栈,出栈,这一系列额外的负荷。所以在这种情况下快排的缺点就会被放大。
std::sort集合了三种算法的优点:
- 在数据量很大的时候采用快排,此时时间复杂度是O(NlogN)。