数据结构-redis数据结构-跳表skiplist

这篇文章简单分享学习redis(6.0)数据结构-跳表skiplist

redis中的有序数据集合[zset],有两种实现方式:跳表和压缩列表,我们今天学习下跳表的实现原理。

学习新的知识,我们先从已掌握的知识入手,由浅入深,让我们先从普通链表开始,如果希望一个集合有序,我们会想到通过有序链表实现:

我们在该单链表中查询元素[15],经过1,3,5,7,9,11,13,15,需要从头到尾遍历8次,效率很低。单链表的查询时间复杂度为O(N)。

如何提升查询效率呢?我们可以为链表建立“索引”:每两个元素提取一层建立索引:

然后我们在新的两层链表中查询元素[15],经过1,5,9,13,15,需要查询5次。通过建立索引达到了减少查询次数的目的。时间复杂度为O(logN)O(logN)。

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

下面我们分析下跳表的时间复杂度如何计算的:

假设我们严格的按照每两个元素提取一层建立索引,如上图的三层索引,N:元素的总规模,h:索引层高

第一层索引元素个数:N/2N/2,

第二层索引元素个数N/2*2N/2∗2,

第三层索引元素个数N/2*2*2N/2∗2∗2

我们可以得到 数据总规模N与索引层高h的函数关系,最底层的索引元素个数为2=N/2h2=N/2h,即可推出h = log2N - 1h=log2N−1,再加上最底层的原始链表 h = log2Nh=log2N (log以2为底N的对数)

跳表的时间复杂度 = 层高(h) * 每层遍历的个数(m),当数据规模很大的时候,我们可以忽略常数项m,所以链表的时间复杂度O(logN)O(logN)

我们上面的例子是为了说明跳表的基本结构,简化的模型,下面再举个更直观的例子,当数据量很大时,可以明显的看到极大的提高查询效率:

 比如查找9998,通过建立索引我们能减少很多的查询过程。



以上我们简单认识了跳表,今天的重点是分析redis中跳表的数据结构。

Redis 的跳跃表实现和 WillianmPugh [WillianmPugh博士在他的论文中提出跳表的数据结构]在 “ Skip Lists: A Probabilistic Alternative to Balanced Trees ” 中描述的跳跃表算法类似,但又有有些区别:

1、Redis 的跳跃表允许分值重复;
2、Redis 的跳跃表排序不止根据分值,在分值相同的时候会对比成员对象;
3、Redis 的跳跃表有一个后退指针,形成了一个双向链表,可以从表尾向表头遍历,用于 ZREVRANGE 命令的实现。

 
Redis的跳跃表由 zskiplistNode 和 skiplist 两个结构定义:

zskiplistNode结构用于表示跳跃表节点;

zskiplist结构则用于保存跳跃表节点的相关信息,比如节点的数量,以及指向表头节点和表尾节点的指针等

skiplis
header:指向跳跃表的表头节点。

tail:指向跳跃表的表尾节点。

ength:记录跳跃表的长度,即除去表头节点之外的节点数量之和。

level:记录跳跃表内层数最大的那个节点的层数(表头节点的层数不计算在内)。

zskiplistNode

ele:用于记录跳跃表节点的值,类型是 SDS。
 

score:保存跳跃表节点的分值,在跳跃表中,节点按各自所保存的分值从小到大排列。

backward:后退指针,它指向当前节点的前一个节点,在程序从表尾向表头遍历时使用。因为一个跳跃表节点只有一个后退指针,所以每次只能后退至前一个节点。
 

level:跳跃表节点的层,每个层都带有两个属性:前进指针 forward 和跨度 span。前进指针用于访问位于表尾方向的其他节点,而跨度则记录了前进指针所指向节点和当前节点的距离。每个跳跃表节点最多有 32 层。

zskiplistLevel包含以下两个属性:

forward:指向同一层的下一个节点,为节点的forward指向NULL 

span:forward指向的节点与本节点之间的节点的个数,span越大说明跳过的节点的个数越多

下面我们分析下跳表插入节点的过程,有助于进一步了解跳表的数据结构及实现原理:

这是第一步查询的要插入的位置的描述:

此处详细分析了查找插入节点的过程分析,因为新增、修改、删除节点都涉及查询


                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值