Redis数据结构——跳跃表

0、简介

zset的编码有压缩链表和跳跃表两种。除了当zset保存的元素少于128个或保存的所有元素大小都小于64字节时使用压缩链表,其余情况都是使用跳跃表
跳跃表,又称跳表是Redis提供的有序集合(zset)类型主要的底层的数据结构。

typedef struct zset {
    dict *dict;
    zskiplist *zsl;  //跳跃表结构:zskiplist
} zset;

1、什么是跳跃表?

跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而到达快速访问节点的目的。

  1. 我们知道在链表中想访问一个数据,需要遍历链表,这样的效率会很低,时间复杂度为O(N)。
    Redis数据结构——跳跃表_第1张图片
  2. 而我们想到可以扩展链表节点,在链表节点上建立多层索引来提高效率。
    eg:访问节点9,本来需要遍历9次,现在加了两层索引之后,只需要遍历3次便可以,查找效率大大提升。
    Redis数据结构——跳跃表_第2张图片
    类似于这种方式的结构就称为跳跃表。

2、Redis中跳跃表的实现

Redis跳跃表是由zskiplistNode和zskiplist两个结构定义,其中zskiplistNode结构用于表示跳跃表节点,而zskiplist结构用于保存跳跃表节点相关信息,比如节点的数量,以及指向表头节点和表尾节点的指针等等。

typedef struct zskiplist {
	//表头节点和表尾节点
	struct zskiplistNode *header, *tail;
	//表中节点的数量(表头节点不计算在内)
	unsigned long length;
	//表中层数最大的节点的层数(表头节点的层数不计算在内)
	int level;
} zskiplist;

结构解释:

  • header:指向跳跃表的表头节点。
  • tail:指向跳跃表的表尾节点。
typedef struct zskiplistNode {
	//层
	struct zskiplistLevel {
		//前进指针
		struct zskiplistNode *forward;
		//跨度
		unsigned int span;
	} level[];
	//后退指针
	struct zskiplistNode *backward;
	//分值
	double score;
	//成员对象
	robj *obj;
} zskiplistNode;

结构解释:

  • forward:每层都有一个指向表尾方向的前进指针,用于从表头向表尾方向访问节点。
  • span:层的跨度。用于记录两个节点之间的距离。
  • backward:节点中用BW字样标记节点的后退指针,它指向位于当前节点的前一个节点。后退指针在程序从表尾向表头遍历时使用。与前进指针所不同的是每个节点只有一个后退指针,因此每次只能后退一个节点。
  • score:各个节点中的1.0、2.0、3.0是节点所保存的分值。在跳跃表中,节点按各自所保存的分值从小到大排列。
  • obj:各个节点中的o1、o2和o3是节点所保存的成员对象。在同一个跳跃表中,各个节点保存的成员对象必须是唯一的,但是多个节点保存的分值却可以是相同的:分值相同的节点将按照成员对象在字典序中的大小来进行排序,成员对象较小的节点会排在前面,而成员对象较大的节点则会排在后面

跳跃表图示如下:
Redis数据结构——跳跃表_第3张图片

你可能感兴趣的:(Redis,redis,数据结构,链表)