GO语言基础语法 | 青训营笔记:GO语言pdqsort算法笔记

92 阅读2分钟

pdqsort是一种不稳定的混合排序算法,是一种融合插入排序,堆排序和优化后的快排的新型排序算法它的不同版本被应用在C++ BOOST、Rust以及Go1.19中。它对常见的序列类型做了特殊的优化,使得在不同条件下都拥有不错的性能。 pdqsort-version1: 如何得知快速排序表现不佳,以及何时切换到堆排序? 当最终pivot的位置离序列两端很接近时(距离小于length/8)判定其表现不佳,当这种情况的次数达到limit(即bits.Len(length))时,切换到堆排序。 对于短序列(<=24)我们使用插入排序,对于其他情况,使用快速排序(选择首个元素作为pivot)来保证整体性能。 当快速排序表现不佳时(limit==0),使用堆排序来保证最坏情况下时间复杂度仍然为O(n*logn)

  • 如何让pdqsort速度更快? 尽量使得QuickSort的pivot为序列的中位数->改进choose pivot Partition速度更快->改进partition,但是此优化在Go表现不好。 pdqsort-version2: 关于pivot的选择: 使用首个元素作为pivot(最简单的方案):实现简单,但是往往效果不好,例如在sorted情况下性能很差。 遍历数组,寻找真正的中位数,遍历对代价很高,性能不好。 ———>寻找近似的中位数。 优化-pivot的选择-----短序列(<=8),选择固定元素 -----中序列(<=50),采样三个元素,nedian of three -----长序列(>50),采样九个元素,median of medians pdqsort-version3: 如何优化重复元素很多的情况: 优化--重复元素较多的情况-----当检测到此时的pivot和上次相同时(发生在leftSubArray),使用partitionEqual将重复元素排列在一起,减少重复元素对于pivot选择的干扰。 当pivot选择策略表现不佳时,随机交换元素(break patterns) 避免一些极端情况使得快排总是表现不佳,以及一些黑客攻击情况。 pdqsort算法的改进在于对常见的情况做了特殊优化,其主要的思想是不断判定目前的序列情况,然后使用不同的方式和路径达到最优解。