未完待续…
跳跃表skiplist
1.简介:
离散,有序的数据结构。和链表、字典等数据结构被广泛地应用在Redis 内部不同, Redis 只在两个地方用到了跳跃表,一个是实现有序集合键,另一个是在集群节点中用作内部数据结构。
2.定义:
/*
* 跳跃表节点
*/
typedef struct zskiplistNode {
robj *obj;// 成员对象,它指向一个字符串对象,而宇符串对象则保存着一个SDS值
double score;// 分值,按此排序
struct zskiplistNode *backward;// 后退指针
struct zskiplistLevel {// 层
struct zskiplistNode *forward;// 前进指针
unsigned int span;// 跨度
} level[];
} zskiplistNode;
/*
* 跳跃表
*/
typedef struct zskiplist {
struct zskiplistNode *header, *tail;// 表头节点和表尾节点
unsigned long length;// 表中节点的数量,表头节点不计算在内
int level;// 表中层数最大的节点的层数,表头节点的层数不计算在内
} zskiplist;
注意:
1.初看上去,很容易以为跨度和遍历操作有关,但实际上并不是这样,遍历操作只使用前进指针就可以完成了,跨度实际上是用来计算排位( rank )的:在查找某个节点的过程中,将沿途访问过的所有层的跨度累计起来,得到的结果就是目标节点在跳跃表中的排位。
举个例子,图5-4 用虚线标记了在跳跃表中查找分值为3.0 、成员对象为o3 的节点时,沿途经历的层z 查找的过程只经过了一个层,并且层的跨度为3 ,所以目标节点在跳跃表中的排位为3。类似的,跨度为1可以累加。
2.住意表头节点和其他节点的构造是一样的:表头节点也有后退指针、分值和成员对象,不过表头节点的这些属性都不会被用到。
3.在同一个跳跃表中,各个节点保存的成员对象必须是唯一的,但是多个节点保存的分值却可以是相同的:分值相同的节点将按照成员对象在字典序中的大小来进行排序。
4.跳跃表节点的level 数组可以包含多个元素,每个元素都包含一个指向其他节点的指针,程序可以通过这些层来加快访问其他节点的速度,一般来说,层的数量越多,访问其他节点的速度就越快。每个跳跃表节点的层高都是1 至32 之间的随机数。