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

188 阅读2分钟

博客图片.webp 这是我参与「第三届青训营 -后端场」笔记创作活动的的第四篇笔记

数据结构与算法

为什么要学习数据结构和算法

数据结构和算法几乎存在于程序开发的所有地方

经典排序算法

插入排序

image.png

将元素不断插入已经排序好的 array中 起始只有一个元素5,其本身是一个有序序列 后续元素插入有序序列中,即不断交换,直到找到第一个比其小的元素

  • 缺点 平均和最坏情况的时间复杂度高达0(n^2)

  • 优点 最好情况时间复杂度为o{n)

快速排序

967494aa-9ee7-4b00-aef5-6b8d8a40fa83.gif 通过选定一个pivot (轴),再从这个轴开始对序列进行分割,分成元素比pivot轴更大和元素比pivot轴更小两个序列,进而通过比较、交换,最终达到有序序列。

  • 缺点 最坏情况的时间复杂度高达0(n^ 2)
  • 优点 平均情况的时间复杂度为0(n*logn)

堆排序

cc1dfde1-f853-405d-a5e6-9acbe8daf704.gif

2.gif

堆排序是建立在树的基础上,利用堆的性质形成的排序算法,构造一个大根堆,再将根节点(最大元素)交换到最后一个位置,调整整个堆,如此反复

  • 缺点 最好情况的时间复杂度高达0 (n*logn)
  • 优点 最坏情况的时间复杂度为0 (n*logn)

Benchmark

使用规则

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

从零开始打造pdqsort

pdqsort简介

pdqsort (pattern-defeating- quicksort)是一种不稳定的混合排序算法,它的不同版本被应用在C++BOOST. Rust 以及Go 1.19 中。它对常见的序列类型做了特殊的优化,使得在不同条件下都拥有不错的性能

  • 关于pivot的选择

    • 使用首个元素作为pivot实现简单,但是往往效果不好
    • 但是寻找中位数的方法又需要遍历数组,性能不好
  • 根据序列长度的不同,来决定选择策略

    • 中序列中,我们采集三种元素,寻找他的中位数。从前中后三个位置选取三种元素,选取三个元素中的中位数。
    • 长序列中,我们采集九种元素,找到它们之间的中位数。
  • 优化重复元素很多的情况

    • 采样时pivot的数量有限,所以不一定会采样到相同的元素
    • 我们可以对两次partition生成的pivot进行比对,如果两个partition生成的pivot相同,则认为此次分割无效