redis基础数据结构(五) 跳跃表

跳跃表是一种对顺序链表的改进,将查找顺序链表的O(N)时间优化为O(logN)时间,空间增加约两倍,有两种常见变体,一种是随机跳跃表,使用随机算法决定每个节点的高度,缺陷有产生随机数的开销;另一种是123确定性跳跃表,除了头和尾,第n层相邻的两个节点之间只有1个,2个或者3个第n-1层的节点,当插入或删除时调整结构;另一种对顺序链表的O(logN)优化是,使用一个指针数组,数组中每个指针指向一个链表节点,从而变成二分查找,得到一个O(logN)的时间界,这种方法需要的空间少,缺陷是在链表增删节点时需要对指针数组进行大量的内存搬移,底层调用C库函数memmove可以防止重叠内存拷贝造成踩内存,但是性能堪忧。

redis的跳跃表使用的是随机跳跃表,代码在server.h和t_zset.c中,server.h提供了跳跃表节点和头的定义,如下

typedef struct zskiplistNode {
    sds ele;
    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;

zskiplistNode是跳跃表节点,包括一个可变长字符串,一个后向指针backward用于指向本节点在level[0]的上一个节点,level结构中每一层都有一个前向指针,以及一个scan表示跨过几个level[0]元素可以达到本层下一个节点。zskiplist是头,包括头尾指针,长度和层数

t_zsets中提供的api:

zslCreateNode:创建一个跳跃表节点,调用者需要提供明确的level

zslCreate:创建一个zskiplist,其结构中有头尾指针,头指针指向一个32层的节点,32层就是支持的最高层数

zslFreeNode:释放一个跳跃表节点的内存,包含其中的sds

zslFree:销毁一个zskiplist,包含所有节点和头的内存释放,方法是顺序遍历level[0]节点

zslRandomLevel:获取一个随机层数,随机算法依据幂率分布,每层节点数约是下一层的1/4

zslInsert:向zskiplist中插入一个节点

zslDeleteNode:在一个zskiplist中删除一个节点,内部函数,调用者需要提供每个level的删除位置

zslDelete:在一个zskiplist中删除一个节点,外部函数,调用者提供score和sds供查找节点,可选择是否保留节点内存

zslValueGteMin:判断value是否比最小值大

zslValueLteMax:判断value是否比最大值小

zslIsInRange:用score判断zskiplist中是否有一部分在range中

zslFirstInRange:找到一个zskiplist中第一个出现在range中的节点

zslLastInRange:找到一个zskiplist中最后一个出现在range中的节点

zslDeleteRangeByScore:删除zskiplist在score范围中的节点

zslDeleteRangeByLex:删除zskiplist在sds范围中的节点

zslDeleteRangeByRank:删除一段索引范围的节点,索引是level[0]中出现的位置

zslGetRank:查找一个节点对应的索引

zslGetElementByRank:通过节点查找一个对应的索引

zslParseRange:将给定的min和max对象解析到range中,关于对象在对象系统中总结

zslParseLexRangeItem:从给定对象中解析出一个sds,并作为range中的一个边界使用

zslFreeLexRange:销毁一个sds的range

zslParseLexRange:读取sds类型的range

sdscmplex:比较两个sds的大小

zslLexValueGteMin:根据提供的值判断是否要更新range中的min

zslLexValueLteMax:根据提供的值判断是否要更新range中的max

zslIsInLexRange:判断zskiplist中是否有一部分在sds的range中

zslFirstInLexRange:查找一个zskiplist中第一个出现在sds的range中的节点

zslLastInLexRange:查找一个zskiplist中最后一个出现在sds的range中的节点

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值