跳表是 有序集合的底层实现之一
定义
跳表节点 zskiplistNode
1 | typedef struct zskiplistNode { |
robj
:保存的对象score
:对象的分值backward
:指向前一个节点的指针level
:层。每次创建一个跳表节点时,程序会根据幂次定律(越大的数字出现的概率越小)随机生成一个介于1~32之间的值作为level
数组的大小,这个大小就是层的高度level.forward
:前进指针,指向下一个同层的节点level.span
:跨度,当前节点和前进指针指向的节点的距离,主要用途是计算排位
跳表 zskiplist
1 | typedef struct zskiplist { |
header
、tail
:分别指向头节点和尾节点length
:表中节点的数量level
:记录表中最高层的节点的层数,不算头节点
多个 zskiplistNode
组成一个跳表,而 zskiplist
结构则保存了跳表的关键信息,使程序可以更方便的操作跳表
zskiplist
的头节点指向一个高度为32的空节点,方便高层跳跃
zset
1 | typedef struct zset { |
跳表是zset的底层实现之一。
尽管跳表可以快速的按照分值定位成员,但是这样的需求远远不够满足 zset 的定义。zset 是一个有序集合,不仅各个节点要按照 score 排序,还必须保证所有节点的成员对象 obj
唯一。因此 zset 以 dict
和 跳表两种数据结构配合使用,满足了有序集合这个定义,而且能以较低的时间复杂度实现增删改查等操作。
总结
- 跳跃表是有序集合的底层实现之一
- Redis的跳跃表实现由zskiplist和zskiplistNode两个结构组成,其中zskiplist用于保存跳跃表信息(比如表头节点、表尾节点、长度),而zskiplistNode则用于表示跳跃表节点
- 每个跳跃表节点的层高都是1至32之间的随机数
- 在同一个跳跃表中,多个节点可以包含相同的分值,但每个节点的成员对象必须是唯一的
- 跳跃表中的节点按照分值大小进行排序,当分值相同时,节点按照成员对象的大小进行排序