Redis的底层数据结构之跳表(有序列表zset的底层数据结构)

跳表概念:

跳表是一个有序的数据结构,它通过内部节点维护的一个指向其他节点的指针,从而达到快速访问的目的。

跳表支持平均时间复杂度为o(logn)的增删查改,最坏的时间复杂度为o(N)

跳表和平衡二叉树的区别:

1. 跳表实现步骤相对平衡二叉树来说相对简单一些。

2.跳表和二叉树都是有序存储的数据结构,他们的查找时间复杂度都是logN。

3.平衡二叉树每次增删节点都需要检查是否需要reblance从而使树达到平衡,而跳表在增删的时候只需要实现局部节点的指针的变化,也就是只需要改变相邻节点的指针。

4. 跳表在区间查询上要好于平衡二叉树,只需要找到起始的区间节点然后向后遍历即可,而平衡二叉树则比跳跃链表操作复杂,如果没有parent节点的话要一个一个找到。

Redis 选择 跳表的原因:

1.区间查找redis 的操作要由于 平衡树。

2.跳表实现相对于二叉树比较简单

3.高并发情况下,红黑树的reblance可能涉及到整棵树,但是跳跃链表只有局部

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

level:level 数组可以包含多个元素,每个元素都包含一个指向其他节点的指针。程序可以通过这些层来加速访问其他节点。
redis.h/zskiplist
typedef struct zskiplist {
     // 表头节点和表尾节点
     structz skiplistNode *header,*tail;
     // 表中节点数量,不包括头结点
     unsigned long length;
     // 表中层数最大的节点的层数,不包括头结点
     int level;
} zskiplist;

header, 指向跳跃表的头结点
tail,   指向跳跃表的尾节点
length, 记录跳跃表中节点的数量,不包含头节点
level,  记录跳跃表中节点的最高层数,不计算头结点层数

增删查改的代码实现着重依赖于找到即将插入节点的路径 这个路径保存在一个零时的update[]数组里面,它记录了即将要插入的节点的previous的指针节点, 数组大小就是level大小,也就是随机出来的当前插入节点最高多少层。 redis中跳表层数的大小随机规则是 最下面的层的分配概率是50% 每上升一层概率减少50%,也就是第二层25%,第三层12.5%...依次次类推。

跳表中还有个属性是 在每一个 leve 数据结构中(也就是包含指向下一个节点的数据结构)有一个属性是span 通过这个属性 可以获取到 当前节点的排名, span储存了从当前节点到下一个节点中间有多少节点,这样要计算排名的话把span进行累加就可以了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值