数据结构与算法|青训营笔记

101 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记。

经典排序算法

插入排序:将元素不断地插入已经排好的array中

时间复杂度:best O(n), avg O(n^2), worst O(n^2)

快速排序:基于分治思想,不断分割序列,整体序列整体有序。选定一个pivot,将序列分成元素比pivot大和比pivot小的两个序列,对两个子序列做同样的操作,直到整体有序

时间复杂度:best O(n*logn), avg O(n*logn), worst O(n^2)

堆排序:利用堆的性质形成的排序算法。先构造一个大顶堆,将根节点(最大元素)交换到最后一个位置,调整整个堆,如此反复

时间复杂度:best O(n*logn), avg O(n*logn), worst O(n*logn)

不同长度随机序列下,三种算法的性能: 短序列(16):插入排序 中序列(128):快速排序 长序列(1024):堆排序 不同长度有序序列下,三中算法的性能比较: 短序列(16):插入排序 中序列(128):插入排序 长序列(1024):插入排序

在所有短序列和元素有序的情况下,插入排序性能最好 在大部分的情况下,快速排序有较好的综合性能 几乎在任何情况下,堆排序的表现都比较稳定

pdqsort

pdqsort是一种不稳定的混合排序算法,对常见的序列类型做了特殊的优化,是的不同条件下都拥有不错的性能

对于短序列(<=24),使用插入排序
其他情况,使用快速排序来保证整体性能
当快速排序多次表现不佳时,使用堆排序来保证最坏情况下时间复杂度仍然为O(n*logn)

如何使快速排序更快

关于pivot的选择:1、使用首元素作为pivot(最简单)
    实现简单,但效果往往不好,如在有序情况下性能很差
2、遍历数组,寻找中位数
    遍历比对代价高,性能差
!平衡两种思路,寻找近似中位数,根据序列长度的不同,来决定选择策略
    短序列(<=8),选择固定元素
    中序列(<=50),采样3个元素,求中位数
    长序列(>50),采样9个元素,求中维素
    pivot的采样方式使得具备探知序列当前状态的能力,采样得到逆序序列,则原序列可能是逆序的,采样得到有序序列,则原序列
    可能是有序的
        发现序列可能逆序,则翻转序列 -> 逆序场景
        序列可能有序,使用优先插入排序 -> 有序场景

优化——重复元素很多的情况

如果两次partition生成的pivot相同,即partition进行了无效分割,此时认为pivot的值为重复元素
当检测到pivot和上次相同时,使用partitionEqual将重复元素排列在一起,减少重复元素对于pivot选择的干扰

优化——当pivot选择策略表现不佳时,随机交换元素

pdqsort最终版本 image.png

时间复杂度:best O(n), avg O(nlogn), worst O(nlogn)

高性能的排序算法如何设计:根据不同情况选择不同策略,取长补短

生产环境中使用的排序算法和课本上的排序算法有什么区别:理论算法注重理论性能,例如时间、空间复杂度等。生产环境中的算法需要面对不同的实践场景,更加注重实践性能