简介
跳跃表是一种有序的数据结构,在每个节点维护多个执行其他节点的指针,从而达到快速到底查询节点的目的。在大部分情况下性能不比平衡树差,并且相对简单,因此很多程序都使用跳表替代平衡树。
结构
如图所示,跳跃表主要有一个zskiplist 和 多个zskiplistNode构成。
zskiplist结构的定义如下:
typedef struct zskiplist {
//表 头 节点 和 表 尾 节 点
structz skiplistNode *header, *tail;
// 表中节点的数量
uns ignedl ong length;
// 表中层数最大的节点的层数
int level;
} zskiplist;
zskiplistNode结构定义:
typedef struct zskiplistNode {
//层
struct zskiplistLevel {
// 前迸指针
struct zskiplistNode *forward;
//跱度
unsigned int span;
) level[];
// 后退指针
struct zskiplistNodebackvard;
// 分值
double score;
// 成员对象
robj *obj;
) zskiplistNode;
跳跃表节点属性
1. 层
- 跳跃表节点的level数组可以包含多个元素,每一个元素指向一个节点,level的元素越多,查找速度就越快。
- 初始化跳跃表节点的时候,redis会根据幂等定律(越大的数值生成的概率越小)生成一个介于1-32 的数值作为跳跃表的level数组的大小。
2. 前进指针
level数值的对象中有一个前进指针,指向其他节点,通过前进指针可以遍历整个跳跃表。下面是一个遍历整个跳跃表的case,虚线表示实际走的前进指针:
3. 跨度
是指当前节点到其他节点直接经过了几个节点,主要是用于排位的计算,举个例子
我们在查找o3的时候经过了一个跨度为3的层,因此o3的排位为3。
4. 后退指针
与前进指针想法,后退指针是进行回退操作的指针。不同的是后退指针只有一个,只能回退到上一个节点
5. score 和 obj
socre是一个浮点数字段,跳跃表会根据score大小进行排序。而节点的obj对象是直接指向一个字符串对象,而字符串对象则保存着一个SDS值
跳跃表
- head 和 tail 指向跳跃表的第一个节点和最后一个节点,可以快速定位头节点和尾节点
- length 标识跳跃表的长度,但是不能超过一定长度
- level属性表示跳跃表节点层最高的level数组的长度
参考: 《Redis 设计与实现》黄健宏 著