2021-07-06

跳跃表介绍

跳跃表(skiplist)是一个有序数据结构,它通过每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。
跳跃表支持平均O(logN)、最坏O(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点。
Redis使用跳跃表来作为有序集合键的底层实现,除了在有序集合键作为底层实现,跳跃表还作为集群节点中内部数据结构的底层实现,Redis只有在这两个地方使用到了跳跃表。

跳跃表的实现

Redis跳跃表由redis.h/zskiplistNode和redis.h/zskiplist两个结构定义,其中zskiplistNode作为跳跃表节点,zskiplist结构则用于保存跳跃表节点的相关信息。

跳跃表节点

跳跃表节点由redis.h/zskiplistNode结构定义:

typedef struct zskiplistNode{
		//层
		struct zskiplistLevel{
				//前进指针
				struct zskiplistNode *forward;
				//跨度
				unsigned int span;
		} level[];
		//后退指针
		struct zskiplistNode *backward;
		//分值
		double score;
		//成员对象
		robj *obj
}zskiplistNode;

  1. 跳跃表节点的level数组可以包含多个元素,每个元素都包含一个指向其他节点的指针,程序可以通过这些层来快速访问其他节点。一般来说,层的数量越多,访问其他节点的速度就会越快。
    每次创建一个新跳跃表节点的时候,程序根据幂次定律(越大的数出现的概率越小)随机生成一个介于1和32之间的数值作为level数组的大小,这个大小就是层的高度。

  2. 前进指针
    每个层都有一个指向表尾方向的前进指针,用于从表头向表尾方向访问节点。下图用虚线表示出了程序从表头向表尾方向,遍历跳跃表中所有节点的路径:
    在这里插入图片描述
    当程序沿着前进指针遍历遇到null时,就表示已经访问到了跳跃表节点的表尾。

  3. 跨度
    层的跨度用于记录两个节点之间的距离:

    • 两个节点之间的跨度值越大,表示两个节点相距越远
    • 指向NULL的所有前进指针的跨度都为0,因为它们没有连向任何节点

跨度实际上是用来计算排位(rank)的:在查找某个节点的过程中,将沿途访问过的所有层的跨度累计起来,得到的结果就是目标节点在跳跃表中的排位。

  1. 后退指针
    节点的后退指针用于从表尾向表头方向访问节点:跟可以一次跳过多个节点的前进指针不同,因为每个节点只有一个后退指针,所以每次只能后退至前一个节点。

  2. 分值和成员
    节点的分值是一个double类型的浮点数,跳跃表中的所有节点都按分值从小到大来排序。
    节点的成员对象是一个指针,它指向一个字符串对象,而字符串对象则保存着一个SDS值。
    在同一个跳跃表中,各个节点保存的成员对象必须是唯一的,但是各个节点的分值可以是不唯一的:
    分值相同的节点将按照成员对象在字典序中的大小来进行排序,成员对象小的节点排在前面(表头方向),成员对象大的节点排在后面(表尾方向)。
    如下图,分值相同,但是成员对象的字典序o1<o2<o3。
    在这里插入图片描述

跳跃表

通过使用一个zskiplist结构来持有这些节点,程序可以更方便的对整个跳跃表进行处理,比如快速访问跳跃表表头节点和表尾节点,或者快速获取跳跃表的节点个数。
zskiplist结构定义如下:

typedef struct zskiplist{
		// 表头节点和表尾节点
		structz skiplistNode  *header, *tail;
		// 表中节点的数量
		unsigned long length;
		// 表中层数最大的节点的层数
		int level;
}zskiplist;

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值