《Redis设计与实现》第五章总结:跳跃表

4.跳跃表

有序集合键的底层实现之一:如果一个有序集合包含的元素数量比较多,或者有序集合中元素是比较长的字符串时,就使用跳表
在集群节点中用作内部数据结构
跳表在Redis中只有这两个用途

4.1 跳表总览

redis.h/zskiplistNode和redis.h/zskiplist两个结构定义,zskiplistNode表示跳表节点,zskiplist用于保存跳表节点的相关信息,如节点数量,头尾指针等

例子:
在这里插入图片描述
如上图,最左边的是zskiplist结构,其属性解释如下:
在这里插入图片描述
而右边的四个为zskiplistNode结构,其属性解释如下:
在这里插入图片描述
下面看看跳表节点和跳表的具体解析

4.2 跳表节点实现

redis.h/zskiplistNode:
在这里插入图片描述
下面逐个分析其属性

4.2.1 层:

每次创建一个新节点时,程序根据幂次定律(越大的数出现的概率越小)随机生成一个介于1到32之间的值作为level数组(level[])的大小,也就是层的高度

例子:
在这里插入图片描述

4.2.1.1 前进指针

每一层都有一个指向表尾方向的前进指针,用于从表头向表尾方向访问节点

例子:虚线表示出了从表头向表尾方向,遍历跳表中所有节点的路径
在这里插入图片描述

4.2.1.2 跨度

每一层的跨度,用于记录两个节点之间的距离

作用:不是用来遍历操作的,因为遍历操作只使用前进指针即可;实际上是用来计算排位的:在查找某个节点的过程中,将沿途访问过的所有层的跨度累计起来,得到的结果就是目标节点在跳表中的排位

例子:虚线标记了在跳表中查找分值为3.0、成员对象为o3的节点时,沿途经历的层;可以看出,查找过程只经过了一个层,且跨度为3,所以此节点排位为3
在这里插入图片描述

4.2.2 后退(BW)指针

用于从表尾向表头方向访问节点

与前进指针区别:前进指针一次可以跳过多个节点,因为每个节点都多个层,每层都有一个前进指针,所以不必限制;后退指针每次只能后退至前一个节点,因为每个节点只有一个后退指针

例子:从表尾向表头遍历,首先通过tail定位到表尾,再通过后退指针遍历即可
在这里插入图片描述

4.2.3 分值和成员对象

成员对象必须唯一,分值则可以重复;分值相同的节点将按照成员对象在字典序中的大小来进行排序,小的靠前

4.3 跳表实现

redis.h/zskiplist:
在这里插入图片描述
虽然仅靠多个跳跃表节点即可组成一个跳表,但是类似链表,使用一个zskiplist结果来持有这些节点,程序可以更方便地对整个跳表进行处理,如快速访问表头和表尾(O(1))、快速获取跳表节点的数量(length属性,O(1))、快速获取层数最高的节点(level,O(1),注意不包括表头)等信息

例子:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41594698/article/details/94178725