分析简单的数据结构算法 | 青训营

44 阅读3分钟

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

数量存储在Redis-zset 中,使用skiplist使得数据完整有序 使用Redis集群,避免单机压力过大,所以我们会选择使用使用主从算法和分片算法。

为了保证集群原信息的稳定,每台Redis都可能单独宕机,所以我们需要使用一致性算法。

后端使用缓存算法降低Redis压力,比如每隔1-2s再去刷新展示排行榜。

由此可见,数据结构和算法几乎存在所有场景。

经典排序算法(插入排序,快速排序,堆排序)

当go版本≤1.18时,使用introsort,后续通过对于基本算法的研究总结,所得算法可能有十倍的提升,会在后期成为Go1.19的默认排序算法。

  • 插入排序(类似洗牌的过程)

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

例:起始只有一个元素5(既是正序也是逆序,其本身是一个有序序列; 后续元素插入到有序序列中,进行不断的交换,直到找到第一个比其小的元素;

这种方法最好的时间复杂度是在O(n), 是在整个序列绝对有序的情况下发生的,平均的时间复杂度是在O(n^2),是由其翻转的对数决定的,最差的复杂度也是O(n^2),其情况自然实在整个序列属于完全逆序的情况下。

缺点:插入排序的时间复杂度很高。

优点:最好的时间复杂度是在O(n)

  • 快速排序

这是一种分治的思想,不断的分割序列直到序列整体有序。

选定一个轴点(pivot),使用pivot分割序列,分成元素比pivot大和元素比pivot小的两个序列。

其最好情况下的时间复杂度是在每次选择的轴点恰好是两个数的中位数,所以其时间复杂度为O(n*logn),而平均时间复杂度也是最好的时间复杂度,最差的时间复杂度是在O(n^2)。

缺点:最差的时间复杂度高达O(n^2)

优点:平均时间复杂度是在O(n*logn)

  • 堆排序,使用堆的性质形成的排序算法

构造一个大顶堆,将根节点(最大的元素)交换到最后的位置,调整整个堆,如此反复 其最好、最差、平均复杂度都为O(n*logn)

缺点:最好时间复杂度高达O(nlogn) 优点最差情况的时间复杂度不会达到O(n^2),也是O(nlogn)

总结

插入排序平均和最坏时间复杂度都是O(n^2),性能会不好,快速排序整体性能处于中间层次,堆排序性能比较稳定,时间复杂度均为O(n*logn)

根据序列元素排序情况分:完全随机情况、有序/逆序情况、元素重复较高情况,在此基础上,会根据序列长度的划分

在短序列和中序列以及长排序中快速排序是效率最高的的,而在中序列中堆排序和快速排序效率几乎一样,插入排序再短序列中速度最快 快速排序在其他情况速度最快,堆排序与速度最快的算法区别并不大

插入排序在序列有序的情况是时间是最快的

实际场景结论:所有短序列和元素有序的情况下,插入排序性能最好,在大多数情况下,快速排序有较好的综合性能,在几乎任何情况下,堆排序表现较稳定(因为时间复杂度较稳定)