交流
商城
MCN
登入
注册
首页
提问
分享
讨论
建议
公告
动态
发表新帖
发表新帖
Redis 1-2、跳跃表数据结构
分享
未结
0
859
李延
LV6
2021-07-19
悬赏:20积分
# 跳跃表算法说明 [https://blog.csdn.net/qpzkobe/article/details/80056807](https://blog.csdn.net/qpzkobe/article/details/80056807) # redis中的数据结构 在server.h中定义 每个节点的定义 ```c typedef struct zskiplistNode { // 节点保存的值 sds ele; //分值 double score; // 后退指针,指向上一个节点 struct zskiplistNode *backward; //层,保存跳跃表每层的数据 struct zskiplistLevel { //前进指针 struct zskiplistNode *forward; //跨度。到下几个节点间隔的数量 unsigned long span; } level[]; } zskiplistNode; ``` 跳跃表定义: ```java typedef struct zskiplist { //跳跃表头、尾节点 struct zskiplistNode *header, *tail; //跳跃表长度 unsigned long length; //跳跃表层层数 int level; } zskiplist; ``` # redis中实现 ## zslInsert 在跳跃表中插入一个节点 ```java //在跳跃表中插入一个节点 zskiplistNode *zslInsert(zskiplist *zsl, double score, sds ele) { //update记录我们要插入的节点在每层节点的最后一个值 zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x; //rank 记录,要插入的节点在每层的位置 unsigned int rank[ZSKIPLIST_MAXLEVEL]; int i, level; serverAssert(!isnan(score)); //获取头节点 x = zsl->header; //从最高层查询 for (i = zsl->level-1; i >= 0; i--) { /* store rank that is crossed to reach the insert position */ //初始化当前层的rank。当是最开始时,为0。其他情况与上一层相同 rank[i] = i == (zsl->level-1) ? 0 : rank[i+1]; /** * 当前层有前进节点,并且 * 当前节点score比要找的小,或者 * 当评分一样,当前节点对象比要找的值小。 * * 说明我们要插入的节点在当前节点的后面 * */ while (x->level[i].forward && (x->level[i].forward->score < score || (x->level[i].forward->score == score && sdscmp(x->level[i].forward->ele,ele) < 0))) { //更新当前rank值,跳跃到下一个节点 rank[i] += x->level[i].span; //x 跟新为前进节点 x = x->level[i].forward; } //退出上面的循环。说明我们要插入的节点在x的前面。将其记录在update中。 update[i] = x; } /* we assume the element is not already inside, since we allow duplicated * scores, reinserting the same element should never happen since the * caller of zslInsert() should test in the hash table if the element is * already inside or not. */ //随机层数, level = zslRandomLevel(); //如果比之前的大,初始化后面rank与update的值 if (level > zsl->level) { for (i = zsl->level; i < level; i++) { rank[i] = 0; update[i] = zsl->header; update[i]->level[i].span = zsl->length; } zsl->level = level; } //为我们插入的数据创建节点 x = zslCreateNode(level,score,ele); //插入数据,在每层中都插入我们的当前节点 for (i = 0; i < level; i++) { x->level[i].forward = update[i]->level[i].forward; update[i]->level[i].forward = x; /* update span covered by update[i] as x is inserted here */ x->level[i].span = update[i]->level[i].span - (rank[0] - rank[i]); update[i]->level[i].span = (rank[0] - rank[i]) + 1; } /* increment span for untouched levels */ //计算我们新加入层数的update值 for (i = level; i < zsl->level; i++) { update[i]->level[i].span++; } //跟新当前节点的backward值 x->backward = (update[0] == zsl->header) ? NULL : update[0]; if (x->level[0].forward) x->level[0].forward->backward = x; else zsl->tail = x; zsl->length++; return x; } ``` ## zslGetElementByRank 根据排序名次查询节点 ```java zskiplistNode* zslGetElementByRank(zskiplist *zsl, unsigned long rank) { zskiplistNode *x; unsigned long traversed = 0; int i; //获取头 x = zsl->header; //从最高层查找,根据span计算下一个节点的名次。 for (i = zsl->level-1; i >= 0; i--) { while (x->level[i].forward && (traversed + x->level[i].span) <= rank) { traversed += x->level[i].span; x = x->level[i].forward; } if (traversed == rank) { return x; } } return NULL; } ```
回帖
消灭零回复
提交回复
热议榜
java 相关知识分享
8
好的程序员与不好的程序员
6
写给工程师的十条精进原则
5
spring boot以jar包运行配置的logback日志文件没生成
5
一步一步分析SpringBoot启动源码(一)
5
MockMvc测试
5
【吐槽向】是不是有个吐槽的板块比较好玩
4
logstash jdbc同步mysql多表数据到elasticsearch
3
IntelliJ IDEA 优质License Server
3
.gitignore忽略规则
3
SpringBoot启动源码分析
3
一步一步分析SpringBoot启动源码(三)
3
2
一步一步分析SpringBoot启动源码(二)
2
积分不够将无法发表新帖
2
官方产品
Meta-Boot - 基于MCN
MCN - 快速构建SpringBoot应用
微信扫码关注公众号