Redis数据结构—跳跃表

大家好,我是白泽,最近学校有点事Redis知识点的更新就放缓了,趁着周六赶紧补一补,我们开始吧~

跳跃表产生的背景

对于有序列表的查找来说,无法找到类似用在有序数组上的二分查找这样的查找算法,因此遍历的效率比较低,跳跃表的出现就是为了提高有序链表的遍历效率

跳跃表的结构

下图是概念上的跳跃表,框中的部分是原始的有序链表,我们将其进行改造,抽离成多层,属于同一列的节点的值相同,这就是一个跳跃表的雏形了(L1、L2、L3是每层对应的头节点,此时共3层),然后我们就能用跳跃表来简化我们的有序链表的查询操作

此时你应该很疑惑,跳跃表是如何从一个有序单列表抽离成很多层的从而得到跳跃表的,很遗憾,跳跃表的建立将设计概率论的一些知识,我认为现在讲解这部分并不合适,所以请假设跳跃表已经由一个有序单列表出发并建立成功了,接下来我们来看看跳跃表是如何简化有序链表的查询操作的

利用跳跃表查询有序链表

查询规则:如果查询目标大于当前值,查当前节点的后一个(同层),如果小于当前值,则下降到当前节点的前一个节点的正下方,并从该节点的后一个开始查询(正下方节点不用查),如果已经下降到第一层,且查到某个值已经大于查询目标的值,则表示目标表示不存在,无需继续查询

  1. 现在我们要查询有序链表中是否存在3这个值,此时跳跃表已经抽离成3层,我们从L3头节点出发,它有一个指向后一个节点的指针,很辛运,后一个节点值为3,查询结束

  1. 现在我们查询有序链表中是否存在值为2.5的节点,依旧从第3层的头节点L3开始查,后一个是值为3的节点,显然,因为链表是有序的,因此往后查将没有结果,所以下降到第2层的L2节点的后一个节点去查,值为1,继续查它的后一位,值为3,因此需要再下降到第1层的值为1的节点的后一个节点开始查询,值为2,继续查后一个节点,值为3,此时无法下降,查询结束

Redis跳跃表图示

Redis的跳跃表本质上就是上面我们提到的跳跃表,它由一个个跳跃表Node节点组成,而整体由一个list表示,由list表示是因为list记录了listNode网络的头指针,尾指针,层数,长度信息,有了list就可以操作跳跃表,这种list的用法出现在绝大多数Redis的数据结构中

光看下面这张图你可能很疑惑,这和上面的跳跃表结构图并不相同,别急,往下看~

Redis跳跃表数据结构

跳跃表的list结构实现

typedef struct zskiplist {
struct zskiplistNode *header, *tail;//表头节点和表尾节点
unsigned long length; //表中的节点数量
int level; //表中层数最大的节点数量
}

跳跃表的Node节点实现

typedef struct zskiplistNode {
//后退指针,指向前一个节点的位置,用于逆向遍历顺序链表
struct zskiplistNode *backward;
//分值,因为需要建立有序链表,因此需要一个值去度量顺序
double score;
//成员对象,用于存放可能需要保存的对象
robj *obj;
//层
struct zskiplistLevel {
//前进指针
struct zskiplistNode *forward;
//跨度(上图箭头上的数值表示跨过了几个节点)
unsigned int span;
} level[];
} zskiplistNode;

listNode中最重要的是level[]数组,这个数组就是图上每个Node节点的L1~Ln的部分,它的作用就是虽然我们整个Redis跳跃表只有n个节点,但是我们在逻辑上将其抽离成了多层:同一列上节点,各个层其实共用一个节点,并没有新创建多余的节点

上面整个跳跃表在Redis中只要4个listNode节点就能组成,且用一个list结构表示,如下:

再说一遍:每个红框只代表一个listNode节点,而它内部的level[]数组,举个例子:

节点A的level[1]的forward属性表示:如果将节点A当作在第一层上,该节点的后一个节点的指针

同理,节点A的level[2]的forward属性表示:如果将节点A当作在第二层,该节点的后一个节点的指针

小结

  1. 你一定要好好理解:level[i]中存放的是第i层上,当前节点的下一个节点的地址,每个节点是被各层共享的,不同的是在各层上,它指向的下一个节点的地址不同

  2. 每层形成长短不一的有序链表,配合下降层数进行有序链表的查询,效率更高

Redis数据结构—跳跃表的更多相关文章

  1. redis skiplist (跳跃表)

    redis skiplist (跳跃表) 概述 redis skiplist 是有序的, 按照分值大小排序 节点中存储多个指向其他节点的指针 结构 zskiplist 结构 // 跳跃表 typede ...

  2. redis的跳跃表

    跳跃表是一种插入.查询.删除的平均时间复杂度为O(nlogn)的数据结构,在最差情况下是O(n),当然这几乎很难出现. 和红黑树相比较 最差时间复杂度要差很多,红黑树是O(nlogn),而跳跃表是O( ...

  3. Redis(2)——跳跃表

    一.跳跃表简介 跳跃表(skiplist)是一种随机化的数据结构,由 William Pugh 在论文<Skip lists: a probabilistic alternative to ba ...

  4. 【Redis】跳跃表原理分析与基本代码实现(java)

    最近开始看Redis设计原理,碰到一个从未遇见的数据结构:跳跃表(skiplist).于是花时间学习了跳表的原理,并用java对其实现. 主要参考以下两本书: <Redis设计与实现>跳表 ...

  5. 用golang实现常用算法与数据结构——跳跃表(Skip list)

    背景 最近在学习 redis,看到redis中使用 了skip list.在网上搜索了一下发现用 golang 实现的 skip list 寥寥无几,性能和并发性也不是特别好,于是决定自己造一个并发安 ...

  6. redis 系列7 数据结构之跳跃表

    一.概述 跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的.在大部分情况下,跳跃表的效率可以和平衡树(关系型数据库的索引就是平衡树 ...

  7. Redis 底层数据结构之跳跃表

    文章参考 <Redis 设计与实现>黄建宏 Redis(2) 跳跃表 跳跃表 跳跃表 skiplist 是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节 ...

  8. [Redis]Redis的设计与实现-链表/字典/跳跃表

    redis的设计与实现:1.假如有一个用户关系模块,要实现一个共同关注功能,计算出两个用户关注了哪些相同的用户,本质上是计算两个用户关注集合的交集,如果使用关系数据库,需要对两个数据表执行join操作 ...

  9. redis 笔记01 简单动态字符串、链表、字典、跳跃表、整数集合、压缩列表

    文中内容摘自<redis设计与实现> 简单动态字符串 1. Redis只会使用C字符串作为字面量,在大多数情况下,Redis使用SDS(Simple Dynamic String,简单动态 ...

随机推荐

  1. 痞子衡嵌入式:盘点国内MCU级RISC-V内核IP厂商

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是国内MCU级RISC-V内核IP厂商. 自RISC-V指令集2010年诞生以来,业界普遍认为,RISC-V将会改变现有的由Arm和Int ...

  2. 6、MyBatis教程之日志实现

    7.日志实现 思考:我们在测试SQL的时候,要是能够在控制台输出 SQL 的话,是不是就能够有更快的排错效率? 如果一个 数据库相关的操作出现了问题,我们可以根据输出的SQL语句快速排查问题. 对于以 ...

  3. Powerful Number 筛学习笔记

    Powerful Number 筛学习笔记 用途 \(Powerful\ number\) 筛可以用来求出一类积性函数的前缀和,最快可以达到根号复杂度. 实现 \(Powerful\ number\) ...

  4. [源码解析] 分布式任务队列 Celery 之启动 Consumer

    [源码解析] 分布式任务队列 Celery 之启动 Consumer 目录 [源码解析] 分布式任务队列 Celery 之启动 Consumer 0x00 摘要 0x01 综述 1.1 kombu.c ...

  5. 基于Hive进行数仓建设的资源元数据信息统计:Spark篇

    在数据仓库建设中,元数据管理是非常重要的环节之一.根据Kimball的数据仓库理论,可以将元数据分为这三类: 技术元数据,如表的存储结构结构.文件的路径 业务元数据,如血缘关系.业务的归属 过程元数据 ...

  6. [Fundamental of Power Electronics]-PART II-7. 交流等效电路建模-7.2 基本交流建模方法

    7.2 基本交流建模方法 在本节中,PWM变换器的交流小信号模型导出步骤将被推导和解释.关键步骤是:(a)利用小纹波近似的动态版本,建立了与电感和电容波形的低频平均值相关的方程式,(b)平均方程的扰动 ...

  7. 带你全面认识CMMI V2.0(五)——改进

    改进(Improving)涉及开发.管理和改进过程及其相关资产,其主要重点是提高组织绩效.保持习惯和持久性可确保过程在整个组织中是持久.习惯性地执行和维持,并有助于有效地实现业务绩效目标.治理(GOV ...

  8. 201871030115-康旭 实验二 软件工程个人项目—《D{0-1} KP》项目报告

    项目 内容 课程班级博客连接 课程班级 这个作业要求连接 作业链接 我的课程学习目标 (1)详细阅读<构建之法>第1章.第2章,掌握PSP流程:(2)设计实际程序掌握动态规划算法.回溯算法 ...

  9. OO电梯系列总结与反思

    目录 前言 HW5 度量分析 UML类图与协作图 bug分析 HW6 度量分析 UML类图与协作图 bug分析 HW7 度量分析 UML类图与协作图 bug分析 SOLID原则 感想 前言 紧张刺激的 ...

  10. Horovod-Usage

    Usage 代码中要包含以下6步: 初始化 Run hvd.init() to initialize Horovod. 将每个GPU固定到单个进程以避免资源争用. 一个线程一个GPU,设置到 loca ...