Redis跳跃表(SkipList)

news2025/7/12 9:56:49

什么是跳跃表

跳跃表(skiplist)是一种有序且随机化的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。


跳跃表的用处

有序集合(zset)的底层可以采用数组、链表、平衡树等结果来实现, 但是他们都有各自的缺点,数组方便查询,但不便于插入和删除;链表方便插入和删除,但是不利于查找;平衡树/红黑树效率高但是实现起来很复杂。

为什么 Redis 不使用这样一些结构呢?

  • 性能考虑: 在高并发的情况下,树形结构需要执行一些类似于 rebalance 这样的可能涉及整棵树的操作,相对来说跳跃表的变化只涉及局部
  • 实现考虑: 在复杂度与红黑树相同的情况下,跳跃表实现起来更简单,看起来也更加直观

所以Redis自己实现了跳跃表来来当做有序集合(zset)的底层实现, 他的查询复杂度平均O(logN), 最坏O(N), 堪比红黑树,但实现起来远比红黑树简单。

跳跃表解决什么问题

先分析一下链表,链表的优势是插入、删除快,查询很慢。对于链表来讲,即便链表中存储的数据是有序的,如果我们要向在其中查找某个数据,它只能从头到尾遍历链表。这样查找效率就会很低,时间复杂度会很高,达到了O(n)。

若要查找值为5的元素,需要从第一个元素依次向后查询,共需比较5次才可以。

假设要查找值为5的元素,可以先在索引层遍历,当遍历到索引层中值为5的元素时就返回。在原单链表中查找值为5的元素,需要遍历比较5次才可以。而现在有了一级索引后,只需要遍历3次就可以找到对应的元素。

 从上个例子中,每加来一层索引后,查找元素需要遍历的次数就会减少,查询效率也得到提升,同理在一级索引的基础上,在加二级索引。

 假设要查找值为6的元素,可以先在索引层遍历,当遍历到索引层中值为7的元素时,则会下降到下层链表层继续查找值为6的元素。

 从图中我们可以看出,查找效率又有了提升,因为在这里例子中我们的数据量很少,当有大量的数据时,我们可以增加多级索引,在查询时,效率可以得到明显的提升。像这种链表增加多种索引的结构,就是 跳跃表

跳跃表是如何进行查找的呢?

  1. 优先从高层查找
  2. 若当前节点的值小于要查找的值,且 next 指针指向大于目标值的节点就降一级寻找,或 next 指针指向了 null ,也需要降一级查找。

与 B+树 对比

,存储就是一个平衡搜索树,如果要插入一个节点那么就检索到这个节点插入,插入的时候要维护子树的规则(平衡搜索树)还有就是 B+树 在 mysql 当中还要在一定的情况下扩容和缩容。这就要消耗一定的资源算力,而跳表这里用随机层数来解决这个问题,这样就解决了插入的消耗问题,比平衡术更加优秀。

由此可见跳表的本质是解决查找问题。

插入元素实现


如果理解上面所说的跳跃表的原理,那么很容易理清楚插入节点时发生的几个动作 (几乎跟链表类似):

  1. 找到当前我需要插入的位置
  2. 创建新节点,调整前后的指针指向,完成插入

跳表的增删改


插入操作

插入操作在实现起来是最麻烦的,需要的考虑的东西最多。插入需要考虑是否插入索引,插入几层等问题。其流程为:

  1. 首先通过上面查找的方式,找到要插入的节点
  2. 插入完这一层,需要考虑上一层是否插入,首先判断当前索引层级,如果大于最大值那么就停止(说明已经到最高索引层)。否则就使用随机化的方法去判断是否向上层插入索引,即产生一个[0-1]的随机数。如果小于0.5就向上插入索引,插入完毕后再次使用随机数判断是否向上插入索引
  3. 继续上的操作,直到概率退出或者索引层数大于最大索引层


删除操作

删除操作比起查询稍微复杂一丢丢,但是比插入简单。删除需要改变链表结构,需要先找到元素,然后对于每个层的相关节点重排前向后向指针,所以需要处理好节点之间的联系,同时还要更新层数。

对于删除操作你需要谨记以下几点:

  1. 删除当前节点和这个节点的前后节点都有关系
  2. 删除当前层节点之后,下一层该key的节点也要删除,一直删除到最底层


更新操作

暂时没做研究
 

总结

  • 跳跃表基于单链表+索引的方式实现
  • 跳跃表是以空间换时间的方式提升了查找速度
  • Redis的跳跃表实现由 zskiplist 和 zskiplistnode 两个结构组成,其中 zskiplist 用于保存跳跃表信息(比如表头节点、表尾节点、长度),而 zskiplistnode 则用于表示跳跃表节点
     

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/108803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

仪表盘读数识别检测 Python+yolov5

仪表读数识别检测利用Pythonyolov5深度学习对仪表盘刻度数进行实时识别检测读取。Python是一种由Guido van Rossum开发的通用编程语言,它很快就变得非常流行,主要是因为它的简单性和代码可读性。它使程序员能够用更少的代码行表达思想,而不会…

艾美捷硫代巴比妥酸反应物质 (TBARS)检测试剂盒试剂准备

艾美捷TBARS(TCA法)测定试剂盒提供了一种简单、可重复和标准化的工具,用于测定血浆、血清、尿液、组织匀浆和细胞裂解物中的脂质过氧化。在高温(90-100C)和酸性条件下,通过MDA和TBA反应形成的MDA-TBA加合物…

kali渗透测试系列---信息收集

kali 渗透测试系列 文章目录kali 渗透测试系列信息收集信息收集 信息收集阶段可以说是在整个渗透测试或者攻击很重要的阶段,毕竟知己知彼才能百战百胜,否则从目标主机使用的平台到数据库的使用再到 web 应用开发的语言等等的种类多如繁星我们一个个的尝…

Opencv(C++)笔记--直方图均衡化、直方图计算

目录 1--直方图均衡化 2--直方图计算 1--直方图均衡化 ① 简述: 对图片的对比度进行调整,输入为灰度图像,对亮度进行归一化处理,提高灰度图的对比度; ② Opencv API: cv::equalizeHist(gray, dst); ③…

Unprojecting_text_with_ellipses过程分析

文章目录一、单应性1. 图片实例2. 数学表达式二、算法思路1. 算法流程2. 透视失真具体解决方案3. 图片旋转具体解决方案4. 图片文字倾斜具体解决方案三、实际处理过程四、算法问题五、OCR识别原文链接 https://mzucker.github.io/2016/10/11/unprojecting-text-with-ellipses.h…

ListView的基本创建方式

ListView的基本创建方式 1.ListView 主要介绍了采用标签创建以及ArrayAdapter适配器以及采用继承ListActivity的方式创建列表项 1.简介 是一个列表控件,以列表的形式展示具体内容,可以给各行设置事件监听器ListView中View负责显示和更新,数据…

最小生成树

文章目录基本原理Kruskal算法Prim算法基本原理 连通图中的每一棵生成树,都是原图的一个极大无环子图,即:从其中删去任何一条边,生成树就不在连通;反之,在其中引入任何一条新边,都会形成一条回路…

二叉树9:二叉树的最大深度

主要是我自己刷题的一些记录过程。如果有错可以指出哦,大家一起进步。 转载代码随想录 原文链接: 代码随想录 leetcode链接: 104. 二叉树的最大深度 559.n叉树的最大深度 104.二叉树的最大深度 题目: 给定一个二叉树&#xff0…

校招面试真题 | 你的期望薪资是多少?为什么

很多人去面试的时候,就像打游戏,过五关斩六将,终于到最后一关了,但是谈薪资的难度堪比打游戏中搞定终级 boss 的难度,真的是太「南」了,好多人都是因为这个问题让自己五味杂陈呀。报高了怕好 offer 失之交臂…

Ubuntu: Docker安装与操作

在进行docker安装前,我们首先得有以下工具:xshell,FileZilla Client Xshell下载安装教程 FileZilla Client下载安装教程 如果你的Ubuntu是纯净的(也就是说刚下好并且刚用虚拟机装好的),你得先 打开终端(CtrlAltT) 一…

远程连接服务器(运用密钥)连接winscp/vscode/mobaxterm

1.连接ssh 先检查自己是否登上校园VPN校园VPN导航页 (xjtu.edu.cn) sslvpn 进入cmd(黑框框) 输入: (1) ssh (用户名)(IP名) -p (端口如22、2022&#x…

基于SSM框架的旅游网站的设计与实现

1 简介 今天向大家介绍一个帮助往届学生完成的毕业设计项目,*基于SSM框架的旅游网站的设计与实现 *。 计算机毕业生设计,课程设计需要帮助的可以找我 2 设计概要 1.1.研究背景 随着互联网技术的飞速发展,网络与我们的生活息息相关,在我们日…

汉诺塔问题的时间复杂度

一、汉诺塔问题 汉诺塔(Tower of Hanoi)是一个经典的递归算法问题。它描述的是有三根杆子和若干个不同大小的圆盘,圆盘可以按照大小顺序放在杆子上。初始时,所有圆盘都放在左边的杆子上,目标是将所有圆盘移动到右边的…

PS CS6视频剪辑基本技巧(三)添加声音和字幕

上一讲,介绍一下视频剪接和添加图片这两个功能。这一讲介绍添加声音和字幕,给上一讲剪接的视频添加一个背景音乐和解说字幕。 目录 一、添加音频 1、添加背景音乐 2、剪掉多余音乐 二、添加字幕 1、制作字幕模板 (1)新建背…

统治扩散模型的U-Net要被取代了,谢赛宁等引入Transformer提出DiT

来自 UC 伯克利的 William Peebles 以及纽约大学的谢赛宁撰文揭秘扩散模型中架构选择的意义,并为未来的生成模型研究提供经验基线。 近几年,在 Transformer 的推动下,机器学习正在经历复兴。过去五年中,用于自然语言处理、计算机视…

【C++】STL——priority_queue的介绍和使用及模拟实现

priority_queue的介绍和使用及模拟实现 文章目录priority_queue的介绍和使用及模拟实现1.priority_queue的介绍和使用priority_queue的介绍priority_queue的使用2. 仿函数3.堆的调整算法堆的向上调整算法堆的向下调整算法4.priority_queue的模拟实现1.priority_queue的介绍和使…

史上最简单易懂的TypeScript教程(更新中)

TypeScript欢迎观看由大型东方幻想车编写的typescript教程1. TypeScript: 类型(1)其他类型欢迎观看由大型东方幻想车编写的typescript教程 TypeScript介绍: TypeScript是JavaScript类型的严格超集,它可以编译成纯JavaScript。TypeScript可以在…

基于VitePress搭建静态文档系统

文章目录前言一、快速上手二、常用配置2.1 类Vue风格首页2.2 顶部导航配置themeConfig.nav2.3 侧边栏导航设置2.3 文档中的链接跳转2.3.1 上一页与下一页2.3.2 文档中链接2.3.3 生成成员页三、进阶配置四、参考代码前言 vitePress:与vue press相似,是一…

Spring中自定义事件监听

目录 一、Spring中的事件监听 二、自定义事件监听 三、例子 1、事件 2、事件监听器 3、事件发布操作 三、测试注意 一、Spring中的事件监听 当处理完一段代码逻辑,后面需要同时执行多个任务,有什么好方法呢?如果在微服务项目中&…

【自用】VUE项目 宝塔部署 上线阿里云服务器CentOS7.6

一、给VUE项目打包 1.开始打包 运行命令: npm run build2.找到打包好的 dist 文件夹 要记住这个dist文件放在了哪儿,记住哦! 二、服务器端安装宝塔面板 1.进入root用户并执行命令 yum install -y wget && wget -O install.…