1. 跳跃表(SkipList)的概念
跳跃列表是一种数据结构。它允许快速查询一个有序连续元素的数据链表
而其快速查询是通过维护一个多层次的链表,且每一层链表中的元素是前一层链表元素的子集。
一开始时,算法在最稀疏的层次进行搜索,直至需要查找的元素在该层两个相邻的元素中间。这时,算法将跳转到下一个层次,重复刚才的搜索,直到找到需要查找的元素为止。跳过的元素的方法可以是随机性选择或确定性选择,其中前者更为常见。
1.1 跳表的特点
(1)由很多层结构组成;
(2)每一层都是一个有序的链表;
(3)最底层(Level 1)的链表包含所有元素;
(4)如果一个元素出现在 Level i 的链表中,则它在 Level i 之下的链表也都会出现;
(5)每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。
普通链表索引找到元素8的过程
使用跳跃链表找到元素8的过程
可以看到查找的速度变快了。
2. 跳跃表在ZSet中的应用
和字典、链表或者字符串这几种在 Redis 中大量使用的数据结构不同, 跳跃表在 Redis 的唯一作用, 就是实现有序集数据类型。
跳跃表将指向有序集的 score
值和 member
域的指针作为元素, 并以 score
值为索引, 对有序集元素进行排序。
举个例子:
127.0.0.1:6379> ZADD oda 6 x 10 y 15 z
(integer) 3
127.0.0.1:6379> ZRANGE oda 0 -1 WITHSCORES
1) "x"
2) "6"
3) "y"
4) "10"
5) "z"
6) "15"
在底层实现中, Redis 为 x
、 y
和 z
三个 member
分别创建了三个字符串, 值分别为 double
类型的 6
、 10
和 15
, 然后用跳跃表将这些指针有序地保存起来, 形成这样一个跳跃表:
总结:
- 跳跃表是一种随机化数据结构,查找、添加、删除操作都可以在对数期望时间下完成。
- 跳跃表目前在 Redis 的唯一作用,就是作为有序集类型的底层数据结构(之一,另一个构成有序集的结构是字典)。
- 为了满足自身的需求,Redis 基于 William Pugh 论文中描述的跳跃表进行了修改,包括:
score
值可重复。- 对比一个元素需要同时检查它的
score
和memeber
。 - 每个节点带有高度为 1 层的后退指针,用于从表尾方向向表头方向迭代。