个人学习的总结学习笔记,参考资料都在文末给出,建议阅读
⭐️内容较多,点赞收藏不迷路 ⭐️
概述
是有序集合的底层实现之一。是一种有序数据结构,通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。
跳跃表是基于多指针有序链表实现的,可以看成多个有序链表。
在 Redis 中,跳跃表被用来实现有序集合健,另一个是在集群节点中用作内部数据结构。
在查找时,从上层指针开始查找,找到对应的区间之后再到下一层去查找。下图演示了查找 22 的过程。
实现
跳表由 redis.h/zskiplistNode 和 redis.h/zskiplist 两个结构定义。
zskiplist
上图最左边,用于保存跳跃表节点的相关信息。
typedef struct zskiplist {
//表头结点和表尾结点
struct zskiplistNode *header, *tail;
//表中结点的数量
unsigned long length;
//表中层数最大的结点的层数
int level;
}
-
header
指向跳跃表的表头结点。
-
tail
指向跳跃表的表尾结点。
-
level
记录目前跳跃表内,层数最大的结点的层数,不包括表头结点。
-
length
记录跳跃表目前包含结点的数量,不包含表头结点。
zskiplistNode
上图最右边的四个,用于表示跳表结点。多个跳表结点可以组成一个跳表。
typedef struct zskiplistNode {
//层
struct zskiplistLevel {
//前进指针
struct zskiplistNode *forward;
//跨度
unsigned int span;
} level[];
//后退指针
struct zskiplistNode *backward;
//分值
double score;
//成员对象
robj *obj;
} zskiplistNode;
-
层(level)
L1表示第一层。层的数量越多,访问其他结点的速度就越快。
随机生成介于 1~32 之间的值作为 level 数组的大小(高度)。
-
前进指针
用于访问位于表尾方向的其他结点。
-
跨度
记录前进指针所指向结点和当前结点的距离。
用来计算排位(rank),将遍历的跨度相加即为目标结点的排位。
-
-
后退指针(backward)
BW标记,指向位于当前结点的前一个结点。
从表尾向表头遍历时,程序首先通过跳表的 tail 指针访问表尾结点。
-
分值(score)
不唯一。
上图中 1.0 2.0 3.0 即为结点分值,从小到大排列。
-
成员对象(obj)
唯一。
o1 o2 o3 即为成员对象。
优点
与红黑树等平衡树相比,跳跃表具有以下优点:
- 插入速度非常快速,因为不需要进行旋转等操作来维护平衡性;
- 更容易实现;
- 支持无锁操作。
拓展阅读
⭐️
如果对你有帮助,请点个赞,加个收藏噢!
参考资料:
《Redis 设计与实现》
cyc2018