6、Redis系统-数据结构-06-跳表

六、跳表(Skiplist)

跳表是一种高效的动态数据结构,可以用于实现有序集合(Sorted Set,Zset)。与平衡树相比,跳表具有实现简单、效率高的优点,因此被 Redis 选用作为有序集合的底层数据结构之一。

1. 跳表的结构设计

跳表通过多级链表的形式实现,每一级链表都跳过一些元素,从而在查询时能够快速跳过不必要的元素。跳表的每个节点包含一个或多个前进指针,这些前进指针指向不同级别的节点,使得跳表具有高效的查询性能。

节点结构

跳表节点的结构定义如下:

typedef struct zskiplistNode {struct zskiplistNode *backward; // 后退指针,指向前一个节点double score;                   // 节点的分值,用于排序sds ele;                        // 节点的元素struct zskiplistLevel {struct zskiplistNode *forward; // 前进指针,指向下一个节点unsigned int span;             // 跨度,表示当前节点和下一个节点之间的距离} level[]; // 按级别划分的前进指针数组
} zskiplistNode;
跳表结构

跳表的结构定义如下:

typedef struct zskiplist {struct zskiplistNode *header, *tail; // 跳表的头节点和尾节点unsigned long length;                // 跳表的长度,即节点数量int level;                           // 跳表的最大级别
} zskiplist;
2. 跳表的操作

跳表支持多种操作,包括插入、删除、查找等。以下是一些常见操作的实现示例:

插入操作

插入新节点时,首先确定新节点的级别,然后在每一级链表中找到插入位置,将新节点插入到相应的位置。

zskiplistNode *zslInsert(zskiplist *zsl, double score, sds ele) {zskiplistNode *update[ZSKIPLIST_MAXLEVEL];unsigned int rank[ZSKIPLIST_MAXLEVEL];int i, level;zskiplistNode *x;x = zsl->header;for (i = zsl->level-1; i >= 0; i--) {rank[i] = i == (zsl->level-1) ? 0 : rank[i+1];while (x->level[i].forward && (x->level[i].forward->score < score || (x->level[i].forward->score == score && sdscmp(x->level[i].forward->ele,ele) < 0))) {rank[i] += x->level[i].span;x = x->level[i].forward;}update[i] = x;}level = zslRandomLevel();if (level > zsl->level) {for (i = zsl->level; i < level; i++) {rank[i] = 0;update[i] = zsl->header;update[i]->level[i].span = zsl->length;}zsl->level = level;}x = zslCreateNode(level,score,ele);for (i = 0; i < level; i++) {x->level[i].forward = update[i]->level[i].forward;update[i]->level[i].forward = x;x->level[i].span = update[i]->level[i].span - (rank[0] - rank[i]);update[i]->level[i].span = (rank[0] - rank[i]) + 1;}for (i = level; i < zsl->level; i++) {update[i]->level[i].span++;}x->backward = (update[0] == zsl->header) ? NULL : update[0];if (x->level[0].forward) x->level[0].forward->backward = x;elsezsl->tail = x;zsl->length++;return x;
}
查找操作

在跳表中查找目标节点时,从最高级别的链表开始,通过前进指针逐级向下查找,直到找到目标节点或确认目标节点不存在。

zskiplistNode *zslFind(zskiplist *zsl, double score, sds ele) {zskiplistNode *x;int i;x = zsl->header;for (i = zsl->level-1; i >= 0; i--) {while (x->level[i].forward && (x->level[i].forward->score < score || (x->level[i].forward->score == score && sdscmp(x->level[i].forward->ele,ele) < 0))) {x = x->level[i].forward;}}x = x->level[0].forward;if (x && score == x->score && sdscmp(x->ele,ele) == 0) {return x;} else {return NULL;}
}
删除操作

删除节点时,通过查找操作确定节点位置,然后在每一级链表中移除该节点,并调整相关节点的前进指针和跨度。

int zslDelete(zskiplist *zsl, double score, sds ele, zskiplistNode **node) {zskiplistNode *update[ZSKIPLIST_MAXLEVEL];zskiplistNode *x;int i;x = zsl->header;for (i = zsl->level-1; i >= 0; i--) {while (x->level[i].forward && (x->level[i].forward->score < score || (x->level[i].forward->score == score && sdscmp(x->level[i].forward->ele,ele) < 0))) {x = x->level[i].forward;}update[i] = x;}x = x->level[0].forward;if (x && score == x->score && sdscmp(x->ele,ele) == 0) {for (i = 0; i < zsl->level; i++) {if (update[i]->level[i].forward == x) {update[i]->level[i].span += x->level[i].span - 1;update[i]->level[i].forward = x->level[i].forward;} else {update[i]->level[i].span -= 1;}}if (x->level[0].forward) {x->level[0].forward->backward = x->backward;} else {zsl->tail = x->backward;}while (zsl->level > 1 && zsl->header->level[zsl->level-1].forward == NULL)zsl->level--;zsl->length--;if (node) *node = x;else zslFreeNode(x);return 1;} else {return 0;}
}
3. 跳表的优点
  1. 高效查询:跳表的查询性能接近于平衡树,时间复杂度为 O(log N)。
  2. 实现简单:与红黑树等平衡树相比,跳表的实现相对简单,容易理解和维护。
  3. 动态调整:跳表能够高效地进行插入和删除操作,同时保持整体结构的有序性。
4. 跳表的使用示例

以下是一些使用 Redis 跳表实现有序集合的示例,展示了如何利用跳表进行数据的存储和操作。

插入数据

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"

获取数据

ZRANGE myzset 0 -1 WITHSCORES
# 1) "one"
# 2) "1"
# 3) "two"
# 4) "2"
# 5) "three"
# 6) "3"

删除数据

ZREM myzset "two"
ZRANGE myzset 0 -1 WITHSCORES
# 1) "one"
# 2) "1"
# 3) "three"
# 4) "3"
结论

通过上述解析,我们可以更好地理解跳表的设计思想和实现原理,从而在实际开发中更好地利用跳表提供的优势。在 Redis 中,跳表通过高效的多级链表结构,实现了有序集合的快速插入、删除和查询操作,适用于需要有序数据存储的场景。了解跳表的内部实现,可以帮助我们在实际应用中更好地利用 Redis 的性能和功能。

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

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

相关文章

阶段三:项目开发---搭建项目前后端系统基础架构:任务13:实现基本的登录功能

任务描述 任务名称&#xff1a; 实现基本的登录功能 知识点&#xff1a; 了解前端Vue项目的基本执行过程 重 点&#xff1a; 构建项目的基本登陆功能 内 容&#xff1a; 通过实现项目的基本登录功能&#xff0c;来了解前端Vue项目的基本执行过程&#xff0c;并完成基…

如何让代码兼容 Python 2 和 Python 3?Future 库助你一臂之力

目录 01Future 是什么? 为什么选择 Future? 安装与配置 02Future 的基本用法 1、兼容 print 函数 2、兼容整数除法 3、兼容 Unicode 字符串 03Future 的高级功能 1. 处理字符串与字节 2. 统一异常处理…

linux kthread任务管理

目录 一、linux 创建内核线程1.1 kthread_create1.2 kthread_create_worker kthread_queue_work 二、设置线程优先级和调度策略2.1 sched_setscheduler2.2 调度策略 一、linux 创建内核线程 1.1 kthread_create 在 linux 中&#xff0c;可以使用 kthread_create 接口创建内核…

移动校园(7)ii:uniapp路由响应拦截器处理token,以及微信小程序报错当前页面正在处于跳转状态,请稍后再进行跳转....

依据昨天的写完&#xff0c;在token过期之后&#xff0c;再次调用接口&#xff0c;会触发后端拦截&#xff0c;扔进全局错误处理中间件 前端说明提示都没有&#xff0c;只有一个这个&#xff0c;现在优化一下&#xff0c;再写一个类似全局后置守卫&#xff0c;当状态码是401的时…

MySQL——数据连接池

数据库连接 --- 执行完毕 --- 释放&#xff08;连接到释放的过程十分浪费系统资源&#xff09; 池化技术&#xff1a;准备一些预先的资源&#xff0c;过来就连接预先准备好的 编写连接池&#xff0c;实现一个接口 DataSource 开源数据源实现&#xff08;拿来即用&#xff09;…

增强安全防护,解读智慧校园系统的登录日志功能

在构建智慧校园系统时&#xff0c;登录日志功能扮演着不可或缺的角色&#xff0c;它不仅是系统安全的守护者&#xff0c;也是提升管理效率和确保合规性的有力工具。这一机制详细记录每次登录尝试的方方面面&#xff0c;涵盖了时间戳、用户身份、登录来源的IP地址乃至使用的设备…

phpcms 升级php8.3.8

windows 2008 server 不支持php8.3.8,需升级为windows 2012 1.下载php8.3.8 PHP8.3.9 For Windows: Binaries and sources Releases 2.配置php.ini (1.)在php目录下找到php.ini-development文件&#xff0c;把它复制一份&#xff0c;改名为php.ini (2.)修改php安装目录 根…

《昇思 25 天学习打卡营第 10 天 | ResNet50 迁移学习 》

《昇思 25 天学习打卡营第 10 天 | ResNet50 迁移学习 》 活动地址&#xff1a;https://xihe.mindspore.cn/events/mindspore-training-camp 签名&#xff1a;Sam9029 使用迁移学习进行狼狗图像分类 简介 在机器学习和深度学习中&#xff0c;我们经常面临数据不足的问题。 迁…

python【文件操作】

文件操作 一、创建文件夹二、文件操作模式1.覆盖写入2.读取3.追加 三、 Python脚本在文件中查找和替换文本四、 python清空文件夹 一、创建文件夹 判断文件或者文件夹是否存在 import ospathrD://测试文件夹 if not os.path.exists(path):os.mkdir(path)print(os.path.exists…

C++模板元编程(二)——完美转发

完美转发指的是函数模板可以将自己的参数“完美”地转发给内部调用的其它函数。所谓完美&#xff0c;即不仅能准确地转发参数的值&#xff0c;还能保证被转发参数的左、右值属性不变。 文章目录 场景旧的方法新的方法内部实现参考文献 场景 思考下面的代码&#xff1a; templ…

高防服务器的重要性

在数字化时代&#xff0c;网络安全已成为企业和个人最为关注的问题之一。随着网络攻击的日益频繁和复杂&#xff0c;传统的服务器租用服务已难以满足高安全需求的市场。高防服务器租用应运而生&#xff0c;成为保护网络安全的重要解决方案。本文将探讨高防服务器租用的概念、重…

专业140+总分420+天津大学815信号与系统考研经验天大电子信息与通信工程,真题,大纲,参考书。

顺利上岸天津大学&#xff0c;专业课815信号与系统140&#xff0c;总分420&#xff0c;总结一些自己的复习经历&#xff0c;希望对于报考天大的同学有些许帮助&#xff0c;少走弯路&#xff0c;顺利上岸。专业课&#xff1a; 815信号与系统&#xff1a;指定教材吴大正&#xf…

2-26 基于matlab开发的制冷循环模型

基于matlab开发的制冷循环模型。Simscape两相流域中的制冷循环模型&#xff0c;在simulink中完成多循环温度控制。程序已调通&#xff0c;可直接运行。 2-26 制冷循环模型 Simscape两相流域 - 小红书 (xiaohongshu.com)

Arduino ESP8266 开发环境搭建

Arduino ESP8266 开发环境搭建 很久之前学嵌入式时&#xff0c;用过Arduino8266进行开发&#xff0c;开发成本低、难度小&#xff0c;体验很不错。 近期&#xff0c;又突然要用&#xff0c;遂再次搭建环境&#xff0c;但变动挺多&#xff0c;有些小波折&#xff0c;开贴记录。…

生成式AI应用实列和价值链

生成式AI应用实列和价值链 生成式AI应用实列ChatGPTGeminiGitHub CopilotSynthesia 价值链 生成式AI应用实列 ChatGPT ChatGPT 并不是生成式 AI 行业中唯一的公司。 Stability AI 的 Stable Diffusion 可以根据文本描述生成图像&#xff0c;发布后 90 天内&#xff0c;在 Git…

vue是如何进行监听数据变化的?vue2和vue3分别是什么,vue3为什么要更换

在 Vue 中&#xff0c;数据变化的监听是通过响应式系统来实现的。Vue 2.x 和 Vue 3 在这方面有一些区别。 Vue 2.x 的数据监听 Vue 2.x 使用的是 Object.defineProperty() 方法来实现数据的响应式。当你声明一个 Vue 实例的数据对象时&#xff0c;Vue 将遍历这个对象的属性&a…

清除屏幕上信息的命令clear

清除屏幕上信息的命令clear There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated should leave quickly. 清…

高考志愿填报千万要注意这四点

在高考志愿填报过程中&#xff0c;确实有很多需要留心的点。我为你总结了四个关键点&#xff0c;希望能帮助你顺利完成志愿填报&#xff1a; 1、学校提供的支持 学校作为学生志愿填报咨询服务的主阵地&#xff0c;应提供体系化和制度化的支持。包括及时关注并传达政策动向和相…

行内元素、块级元素居中

行内元素居中 水平居中 {text-align&#xff1a;center;}垂直居中 单行——行高等于盒子高度 <head><style>.father {width: 400px;height: 200px;/* 行高等于盒子高度&#xff1a;line-height: 200px; */line-height: 200px;background-color: pink;}.son {}&…

如何做好IT类的技术面试?

我们在找工作时&#xff0c;需要结合自己的现状&#xff0c;针对意向企业做好充分准备。作为程序员&#xff0c;你有哪些面试IT技术岗的技巧&#xff1f; 方向一&#xff1a;分享你面试IT公司的小技巧 我分享一些基于广泛观察和用户反馈的面试IT公司的小技巧&#xff1a; 技术准…