业务开发算法 50 讲
黄清昊
Hashdata 数据库内核工程师,LeetCode 高赞答主,公众号微扰理论作者
23292 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 51 讲
业务开发算法 50 讲
15
15
1.0x
00:00/00:00
登录|注册

31|跳表:Redis是如何存储有序集合的?

删除节点
搜索目标节点
代码实现
插入过程
抛硬币策略
维护成本问题
理想状态
代码实现
节点值
向右、向下指针
捷径的增加
分层链表
讨论与分享
尝试实现整个跳表
实现跳表的删除操作
适用于Redis有序集合
支持范围查询
实现简单
时间复杂度O(logN)
空间复杂度O(N)
删除操作
引入随机性
完美跳表
跳表的搜索过程
跳表节点定义
跳表的设计思想
有序链表的查询问题
链表结构图
跳表的动机:链表结构的优化
树状结构的局限性
优化思路:有序结构快速查找
链表的有序存储问题
课后作业
跳表的优势与应用
跳表的设计与实现
跳表的诞生
跳表:Redis是如何存储有序集合的?

该思维导图由 AI 生成,仅供参考

你好,我是微扰君。
上一讲我们一起学习了布隆过滤器,它可以帮助我们用更低的存储成本、更高效地判断某个元素是否在一个集合中出现,当然代价是一定的误判率。总的来说,布隆过滤器特别适合用来解决 Redis 中缓存穿透的问题。
今天,我们同样来讨论一个在 Redis 中发挥巨大作用的数据结构:跳表。如果你有一定的 Redis 使用经验,常用的 ZSET 底层实现就是基于跳表的。
跳表这个数据结构,其实在之前介绍红黑树的时候我们简单提到过,和红黑树一样,它可以非常高效地维护有序键值对,插入、查询和删除的平均时间复杂度都是 O(logN),所以被 Redis 用来存储有序集合。但在时空复杂度差不多的情况下,跳表比红黑树实现起来要简洁优雅得多。
我个人认为,跳表几乎在每个方面都比红黑树更好,当然红黑树由于发明更早,得到了更广泛的应用,所以很多 TreeMap 之类的语言原生的数据结构还是常常采用红黑树。但是跳表作为一种非常高效的有序集合的实现,背后的原理很值得我们学习。
那跳表是如何设计、实现的呢,我们开始今天的学习之旅。

跳表为什么诞生

故事的开头,还是要从链表说起。
之前讲红黑树(点这里复习)我们也提到,如果要实现一个字典这样的数据结构,其实可以直接用一个线性数据结构,来存储所有的元素,至于每次插入元素前如何判断元素是否存在,也很简单,遍历一遍就可以了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

跳表是一种在Redis中发挥重要作用的数据结构,特别适合存储有序集合。与红黑树相比,跳表的实现更为简洁优雅,几乎在每个方面都更胜一筹。跳表的设计动机源于对链表存储有序集合时查询效率低下的问题,通过在链表上增加多层索引,实现了类似平衡二叉搜索树的快速搜索效果。跳表节点的基本数据结构包括向右和向下的指针,通过这些指针可以维护整个多层的跳表结构。跳表的搜索过程是从左上到右下进行的,通过左右寻找目标区间和向下走的方式实现对目标值的查找。跳表的实现原理涉及如何维护多层链表结构以及在合适的时机加入新的层,以保证高效查询同时不带来过高的维护成本。跳表的设计思想类似于换乘公共交通,通过增加间距更大的“站”实现快速搜索。引入随机性的跳表通过搜索并记录路径,可以在保持跳表查询效率的同时,快捷地插入元素,降低维护成本。虽然单点查询的效率不如哈希表,但跳表可以很好地支持范围查询,这一点比红黑树也有明显优势。总的来说,跳表作为一种高效的有序集合实现,背后的原理值得深入学习。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《业务开发算法 50 讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(3)

  • 最新
  • 精选
  • 小白哥哥
    跳表和红黑树比唯一的劣势可能就是整体内存占的多一些了

    作者回复: 嗯嗯 我觉得跳表比红黑树好用很多~

    2022-03-17
    2
  • 音目
    深入浅出,非常易懂。大佬太棒了

    作者回复: 感谢夸奖;觉得有帮助的话也可以分享给朋友一起学习哦。 有问题可以+v: constant_variation

    2022-05-02
    1
  • Geek_8941b4
    使用 while 循环回溯,用 new Node(right, down, val) 新建每一层的节点。所以跳表的层数本质上是有多少层就有多少个相同的节点向上叠加。这个代码真的优雅
    2022-07-14
    1
收起评论
显示
设置
留言
3
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部