Go排序算法 | 青训营笔记

97 阅读3分钟

此章节学习Go1.19采用的pdqsort(pattern-defeating quicksort)算法。pdqsort是一个快速的、自适应的排序算法,一种融合插入排序、堆排序和优化后的快排的新型排序算法。在大多数情况下比标准的快速排序更快,且在一些特定情况下能够避免最坏情况的发生,从而保证排序的稳定性和高效性,实现高性能排序。

数据结构与算法

数据结构和算法对于计算机科学和软件开发非常重要,可以提高程序的性能、可维护性和可扩展性,帮助解决复杂的问题,并为技术决策提供支持。例如为什么 MySQL 采用 B+ 树作为索引?合适的数据结构将更有助于优化以及解决问题。本节中将介绍高效的排序算法pdqsort,那么Go1.19的排序算法是如何设计的?

经典排序算法

  • 插入排序(Insection sort)
    插入排序通过构建有序序列,对于未排序部分的每个元素,在已排序部分中找到合适的位置并插入。时间复杂度为 O(n^2),最好情况为O(n)。

  • 快速排序(Quick sort)
    快速排序选择一个基准元素,将待排序序列分割成两个子序列,使得左边的子序列中的元素都小于等于基准元素, 右边的子序列中的元素都大于等于基准元素。然后递归地对左右子序列进行快速排序,从而实现整个序列的排序, 快速排序的时间复杂度平均为O(nlogn)。

  • 堆排序(Heap sort)
    堆排序是一种基于二叉堆数据结构的排序算法,通过构建最大堆(或最小堆)来进行排序,时间复杂度O(nlogn)。

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

pdqsort

  • version1
    结合三种排序方法的优点
    对于短序列(小于一定长度)我们使用插入排序,短序列<=24
    其他情况,使用快速排序来保证整体性能
    当快速排序表现不佳时,使用堆排序来保证最坏情况下时间复杂度仍然为O(n*logn)

  • version2
    关于pivot的选择优化,寻找近似中位数
    发现序列可能逆序,则翻转序列->应对reverse场景
    发现序列可能有序使用有限插入排序->应对sorted场景

  • final version
    重复元素较多的情况
    当检测到此时的pivot和上次相同时,使用partitionEqual将重复元素排列在一起,减少重复元素对于pivot选择的干扰。
    当pivot选择策略表现不佳时,随机交换元素。

image.png

学习体验

关于GO1.19排序算法的实现有了认识和了解,对于Go的学习还是很有帮助的。关于Go的架构组成及其实现原理还需深入学习!
Go!