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

108 阅读2分钟

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

三种常用排序

理论复杂度:

最优平均最差
插入排序O(N)O(N^2)O(N^2)
快排O(NlogN)O(NlogN)O(N^2)
堆排O(NlogN)O(NlogN)O(NlogN)

插入排序:元素少的时候很快,相对有序的时候很快

快排:随机乱序下优秀,普遍情况下很快。逆序情况下退化为O(N^2)

堆排:稳定

随机序列情况下测试:

短序列 (~16)中序列 (~128)长序列 (~1024)
插入排序最快最慢最慢
快排最慢最快最快
堆排中间中间中间
  • 快排:短序列下快排递归导致的栈开销比排序本身开销更大
  • 插入排序:短序列下插入排序的两重循环是非常快的
  • 堆排:建堆操作在短序列情况下的开销也会大于排序本身
  • 中长序列下复杂度符合理论复杂度分析,对于快排比堆排快的是因为快排使用分治+递归,复杂度约为O(NlogN),而堆排需要建堆和排序两个操作,那么实际的复杂度要在O(NlogN)前乘上系数2 。

有序情况下测试:

短序列 (~16)中序列 (~128)长序列 (~1024)
插入排序最快最快最快
快排最慢最慢最慢
堆排中间中间中间

有序情况下插入排序是最优解,O(N) 复杂度。

而堆排序在有序情况下建堆操作的复杂度降为O(N),所以复杂度优于快排。

PdqSort

pdqSort 是基于快排的一个改进版本,进行了一些策略上的优化

最优平均最差
PdqSortO(N)O(NlogN)O(NlogN)

原理:插入排序、堆排、快排的综合使用

版本1:

  • 元素个数小于等于 24 后转插入排序
  • pivot 取首元素
  • 左右大小相差很大时就是表现不佳转快排 (pivot 位置离两端很接近且次数达到 limit )

版本2:

  • pivot 取哪儿 - 根据长度不同决定选择策略

    • 短(~10): 中值
    • 中(~50): 三数选中法
    • 长(>50): 九数选中法
  • pivot 采样方式使我们可探知当前状态

    • 采样元素都是逆序 - 可能序列就是逆序 - 翻转
    • 同理,推测正序情况直接插排
    • 考虑误判和优化之间的平衡
    • 插入排序使用限制次数的插入排序
    • 如果误判,调整返回
  • 重复度较高

    • pivot 检测重复度,不好,效率不高
    • 如果两次 partition 生产的 pivot 相同,即进行了无效分割,对重复元素进行处理
    • 当 pivot 选择表现不佳, 在limit - 1 的同时,随机交换一些元素,避免极端情况和黑客恶意攻击