Redis为什么用跳表实现有序集合

news2024/11/5 20:21:39

Redis为什么用跳表实现有序集合

手写一个跳表

为了更好的回答上述问题以及更好的理解和掌握跳表,这里可以通过手写一个简单的跳表的形式来帮助读者理解跳表这个数据结构。

我们都知道有序链表在添加、查询、删除的平均时间复杂都都是 O(n) 即线性增长,所以一旦节点数量达到一定体量后其性能表现就会非常差劲。而跳表我们完全可以理解为在原始链表基础上,建立多级索引,通过多级索引检索定位将增删改查的时间复杂度变为 O(log n)

可能这里说的有些抽象,我们举个例子,以下图跳表为例,其原始链表存储按序存储 1-10,有 2 级索引,每级索引的索引个数都是基于下层元素个数的一半。

img

假如我们需要查询元素 6,其工作流程如下:

  1. 从 2 级索引开始,先来到节点 4。

  2. 查看 4 的后继节点,是 8 的 2 级索引,这个值大于 6,说明 2 级索引后续的索引都是大于 6 的,没有再往后搜寻的必要,我们索引向下查找。

  3. 来到 4 的 1 级索引,比对其后继节点为 6,查找结束。

相较于原始有序链表需要 6 次,我们的跳表通过建立多级索引,我们只需两次就直接定位到了目标元素,其查寻的复杂度被直接优化为O(log n)

img

对应的添加也是一个道理,假如我们需要在这个有序集合中添加一个元素 7,那么我们就需要通过跳表找到小于元素 7 的最大值,也就是下图元素 6 的位置,将其插入到元素 6 的后面,让元素 6 的索引指向新插入的节点 7,其工作流程如下:

  1. 从 2 级索引开始定位到了元素 4 的索引。

  2. 查看索引 4 的后继索引为 8,索引向下推进。

  3. 来到 1 级索引,发现索引 4 后继索引为 6,小于插入元素 7,指针推进到索引 6 位置。

  4. 继续比较 6 的后继节点为索引 8,大于元素 7,索引继续向下。

  5. 最终我们来到 6 的原始节点,发现其后继节点为 7,指针没有继续向下的空间,自此我们可知元素 6 就是小于插入元素 7 的最大值,于是便将元素 7 插入。

img

这里我们又面临一个问题,我们是否需要为元素 7 建立索引,索引多高合适?

我们上文提到,理想情况是每一层索引是下一层元素个数的二分之一,假设我们的总共有 16 个元素,对应各级索引元素个数应该是:

1. 一级索引:16/2=8
2. 二级索引:8/2 =4
3. 三级索引:4/2=2

由此我们用数学归纳法可知:

1. 一级索引:16/2=16/2^1=8
2. 二级索引:8/2 => 16/2^2 =4
3. 三级索引:4/2=>16/2^3=2

假设元素个数为 n,那么对应 k 层索引的元素个数 r 计算公式为:

r=n/2^k

同理我们再来推断以下索引的最大高度,一般来说最高级索引的元素个数为 2,我们设元素总个数为 n,索引高度为 h,代入上述公式可得:

2= n/2^h
=> 2*2^h=n
=> 2^(h+1)=n
=> h+1=log2^n
=> h=log2^n -1

而 Redis 又是内存数据库,我们假设元素最大个数是65536,我们把65536代入上述公式可知最大高度为 16。所以我们建议添加一个元素后为其建立的索引高度不超过 16。

因为我们要求尽可能保证每一个上级索引都是下级索引的一半,在实现高度生成算法时,我们可以这样设计:

  1. 跳表的高度计算从原始链表开始,即默认情况下插入的元素的高度为 1,代表没有索引,只有元素节点。

  2. 设计一个为插入元素生成节点索引高度 level 的方法。

  3. 进行一次随机运算,随机数值范围为 0-1 之间。

  4. 如果随机数大于 0.5 则为当前元素添加一级索引,自此我们保证生成一级索引的概率为 50% ,这也就保证了 1 级索引理想情况下只有一半的元素会生成索引。

  5. 同理后续每次随机算法得到的值大于 0.5 时,我们的索引高度就加 1,这样就可以保证节点生成的 2 级索引概率为 25% ,3 级索引为 12.5% ……

我们回过头,上述插入 7 之后,我们通过随机算法得到 2,即要为其建立 1 级索引:

img

最后我们再来说说删除,假设我们这里要删除元素 10,我们必须定位到当前跳表各层元素小于 10 的最大值,索引执行步骤为:

  1. 2 级索引 4 的后继节点为 8,指针推进。

  2. 索引 8 无后继节点,该层无要删除的元素,指针直接向下。

  3. 1 级索引 8 后继节点为 10,说明 1 级索引 8 在进行删除时需要将自己的指针和 1 级索引 10 断开联系,将 10 删除。

  4. 1 级索引完成定位后,指针向下,后继节点为 9,指针推进。

  5. 9 的后继节点为 10,同理需要让其指向 null,将 10 删除。

img

总结:

有几个原因:

1、它们不是很占用内存。这主要取决于你。改变节点拥有给定层数的概率的参数,会使它们比 B 树更节省内存。

2、有序集合经常是许多 ZRANGE 或 ZREVRANGE 操作的目标,也就是说,以链表的方式遍历跳表。通过这种操作,跳表的缓存局部性至少和其他类型的平衡树一样好。

3、它们更容易实现、调试等等。例如,由于跳表的简单性,我收到了一个补丁(已经在 Redis 主分支中),用增强的跳表实现了O(log(N))的 ZRANK。它只需要对代码做很少的修改。

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

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

相关文章

影刀RPA实战:嵌入python,如虎添翼

1. 影刀RPA与Python的关系 影刀RPA与Python的关系可以从以下几个方面来理解: 技术互补:影刀RPA是一种自动化工具,它允许用户通过图形化界面创建自动化流程,而Python是一种编程语言,常用于编写自动化脚本。影刀RPA可以…

GR2——在大规模视频数据集上预训练且机器人数据上微调,随后预测动作轨迹和视频(含GR1详解)

前言 上个月的24年10.9日,我在朋友圈看到字节发了个机器人大模型GR2,立马去看了下其论文(当然了,本质是个技术报告) 那天之后,我就一直想解读这个GR2来着 然,意外来了,如此文《OmniH2O——通用灵巧且可全…

HarmonyOS NEXT应用元服务开发组合场景

在一些场景中,一个功能上完整的UI对象可能是由若干个更小的UI组件组合而成的。若每一个小的UI组件都可以获焦并朗读,则会造成信息冗余和效率降低。同时由于可聚焦的组件过多过细,也会影响触摸浏览时走焦的性能体验。在这种情况下,…

2024双11高端家用投影仪哪个牌子好?当贝因何力压极米坚果

随着生活水平的日益提升与科技的飞速进步,人们不只通过外出游玩来获得身心的愉悦,也通过提升家庭娱乐生活的品质,来获得足不出户的快乐。在2024年双11购物狂欢节之际,很多家庭都纷纷将高端家用投影仪加入购物清单,但各…

SpringBoot day 1104

ok了家人们这周学习SpringBoot的使用,和深入了解,letgo 一.SpringBoot简介 1.1 设计初衷 目前我们开发的过程当中,一般采用一个单体应用的开发采用 SSM 等框架进行开发,并在 开发的过程当中使用了大量的 xml 等配置文件&#x…

HCIP(7)-边界网关协议BGP基本配置(对等体peer,宣告network,引入import)

边界网关协议(Border Gateway Protocol,BGP)是一种用来在路由选择域之间交换网络层可达性信息(Network Layer Reachability Information,NLRI)的路由选择协议。由于不同的管理机构分别控制着他们各自的路由…

算法: 链表题目练习

文章目录 链表题目练习两数相加两两交换链表中的节点重排链表合并 K 个升序链表K 个一组翻转链表 总结 链表题目练习 两数相加 坑: 两个链表都遍历完后,可能需要进位. class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode cur1 l1;ListNode…

HTML 基础标签——元数据标签 <meta>

文章目录 1. `<meta>` 标签概述2. 属性详解2.1 `charset` 属性2.2 `name` 属性2.3 `content` 属性2.4 `http-equiv` 属性3. 其他常见属性小结在 HTML 文档中,元数据标签 <meta> 是一种重要的标签,用于提供关于文档的信息,这些信息不直接显示在网页内容中,但对于…

新闻稿件管理系统:SpringBoot框架深度解析

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

【网络】自定义协议——序列化和反序列化

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解什么是序列化和分序列&#xff0c;并且自己能手撕网络版的计算器。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不…

CTFshow之信息收集第1关到10关。详细讲解

得而不惜就该死&#xff01; --章总 开始新的篇章&#xff01; 零、目录 一、实验准备 1、ctf网站&#xff1a;ctf.show 2、工具&#xff1a;chrome浏览器、hackbar插件 3、burpsuite抓包工具 二、实验技巧 &#xff08;一&#xff09;F12摸奖 源码泄露 &#xff08;二…

Redis ——发布订阅

问题引入&#xff1a; 服务器A、B、C、D&#xff0c;客户端&#xff1a;C1&#xff0c;C2&#xff0c;C3&#xff0c;C4&#xff1b; 客户端基于集群聊天服务器的负载均衡分配&#xff1b; C1 被分配到A&#xff0c;C2 被分配到B&#xff0c;C3 被分配到C&#xff0c;C4 被分…

【漏洞复现】某平台-QRcodeBuildAction-LoginSSO-delay-mssql-sql注入漏洞

《Java代码审计》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484219&idx1&sn73564e316a4c9794019f15dd6b3ba9f6&chksmc0e47a67f793f371e9f6a4fbc06e7929cb1480b7320fae34c32563307df3a28aca49d1a4addd&scene21#wechat_redirect 《Web安全》h…

API网关 - JWT认证 ; 原理概述与具体实践样例

API网关主要提供的能力&#xff0c;就是协议转换&#xff0c;安全&#xff0c;限流等能力。 本文主要是分享 如何基于API网关实现 JWT 认证 。 包含了JWT认证的流程&#xff0c;原理&#xff0c;与具体的配置样例 API网关认证的重要性 在现代Web应用和微服务架构中&#x…

Excel:vba实现批量插入图片

实现的效果&#xff1a; 实现的代码&#xff1a; Sub InsertImageNamesAndPictures()Dim PicPath As StringDim PicName As StringDim PicFullPath As StringDim RowNum As IntegerDim Pic As ObjectDim Name As String 防止表格里面有脏数据Cells.Clear 遍历工作表中的每个图…

什么是 OpenTelemetry?

OpenTelemetry 定义 OpenTelemetry (OTel) 是一个开源可观测性框架&#xff0c;允许开发团队以单一、统一的格式生成、处理和传输遥测数据&#xff08;telemetry data&#xff09;。它由云原生计算基金会 (CNCF) 开发&#xff0c;旨在提供标准化协议和工具&#xff0c;用于收集…

电商美工必备神器:千鹿 AI 轻松解决场景图主图尺寸问题

前言 在电商领域&#xff0c;美工在做详情页设计时&#xff0c;常常会为图片尺寸问题而苦恼。而 AI 扩图在此刻就成为了美工们的得力助手。其中&#xff0c;场景图主图太小是一个让人颇为头疼的难题。千鹿 AI 作为一款强大的工具&#xff0c;能够一键将图片改成指定尺寸&#…

关于 PDF 抽取的吐槽

今天一下午写了8&#xff0c;9个 PDF 抽取的脚本。最后又回归最开始简单的模式了&#xff0c;要疯了&#xff0c;谁懂啊。 我是下午的工作是这样的(我是这么疯的) 最开始使用最简单的策略&#xff0c;先使用 PyPDF2.PdfReader(file) 读取文件&#xff0c;然后在每一页使用 pag…

无人机避障——(局部规划方法)DWA(动态窗口法)

传统的DWA算法更加倾向于车辆等差速无人车&#xff0c;旋翼无人机是全速的&#xff0c;全向的。 全局路径是通过A*算法生成的 局部路径规划效果&#xff1a; DWA算法效果&#xff1a; 过程图&#xff1a; 完整过程&#xff1a; PID算法效果&#xff1a; 过程图&#xff1a…

知识吾爱纯净版小程序系统 leibiao SQL注入漏洞复现(XVE-2024-30663)

0x01 产品简介 知识吾爱纯净版小程序系统是一款基于微信小程序平台开发的知识付费应用,旨在帮助用户快速建立自己的知识付费平台,实现支付变现和流量主收益。它提供了简洁明了的用户界面和良好的用户体验,同时注重用户隐私保护,确保用户信息的安全存储和传输。 0x02 漏洞…