# [redis设计与实现][4]基本数据结构——跳跃表

Redis使用跳跃表和字典共同来实现有序集合键(sorted set)。

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

[cce lang=”c”]
typedef struct zskiplist {
//跳跃表头、尾指针
//跳跃表长度
unsigned long length;
//跳跃表层数
int level;
} zskiplist;
[/cce]

zskiplist *zslCreate(void);
[cce lang=”c”]
zskiplist *zslCreate(void) {
int j;
zskiplist *zsl;

zsl = zmalloc(sizeof(*zsl));
zsl->level = 1;
zsl->length = 0;
//创建头节点，头节点永远有最高层
//#define ZSKIPLIST_MAXLEVEL 32 /* Should be enough for 2^32 elements */
//初始化头节点的每一层
for (j = 0; j < ZSKIPLIST_MAXLEVEL; j++) {
}
zsl->tail = NULL;
return zsl;
}
zskiplistNode *zslCreateNode(int level, double score, robj *obj) {
zskiplistNode *zn = zmalloc(sizeof(*zn)+level*sizeof(struct zskiplistLevel));
zn->score = score;
zn->obj = obj;
return zn;
}
[/cce]
zskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj);
[cce lang=”c”]
zskiplistNode *zslInsert(zskiplist *zsl, double score, robj *obj) {
zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
unsigned int rank[ZSKIPLIST_MAXLEVEL];
int i, level;

redisAssert(!isnan(score));
//遍历查找当前score对应的插入位置
for (i = zsl->level-1; i >= 0; i–) {
/* store rank that is crossed to reach the insert position */
rank[i] = i == (zsl->level-1) ? 0 : rank[i+1];
while (x->level[i].forward &&
(x->level[i].forward->score < score ||
(x->level[i].forward->score == score &&
compareStringObjects(x->level[i].forward->obj,obj) < 0))) {
//累加跨度
rank[i] += x->level[i].span;
x = x->level[i].forward;
}
//当前层要更新的节点
update[i] = x;
}
/* we assume the key is not already inside, since we allow duplicated
* scores, and the re-insertion of score and redis object should never
* happen since the caller of zslInsert() should test in the hash table
* if the element is already inside or not. */
//随机一个当前节点的层数
level = zslRandomLevel();
//如果是最高层，需要修正
//在以前最高层以上的，跨度都修复为跳跃表原长度，前置节点都改为头结点
if (level > zsl->level) {
for (i = zsl->level; i < level; i++) {
rank[i] = 0;
update[i]->level[i].span = zsl->length;
}
//跳跃表的总层数改成最新的层数
zsl->level = level;
}
x = zslCreateNode(level,score,obj);
//每一层的链表构建
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 */
for (i = level; i < zsl->level; i++) {
update[i]->level[i].span++;
}

//修改当前节点的前置节点等
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;
}
int zslRandomLevel(void) {
int level = 1;
//#define ZSKIPLIST_P 0.25 /* Skiplist P = 1/4 */
while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
level += 1;
return (level }
[/cce])>

)>

|
2月前
|

Redis相关命令详解及其原理:Redis基本操作、数据结构以及应用
Redis相关命令详解及其原理:Redis基本操作、数据结构以及应用
75 0
|
25天前
|

58 1
|
27天前
|

Redis数据结构的奇妙世界：一窥底层存储机制【redis第一部分】
Redis数据结构的奇妙世界：一窥底层存储机制【redis第一部分】
35 0
|
2月前
|

Redis Stream 数据结构实现原理真的很强
Redis Stream 数据结构实现原理真的很强
28 0
|
2月前
|

Redis Set 用了 2 种数据结构来存储，到现在才知道
Redis Set 用了 2 种数据结构来存储，到现在才知道
24 0
|
2月前
|

Redis List 底层三种数据结构原理剖析
Redis List 底层三种数据结构原理剖析
23 0
|
2月前
|

31 0
|
2月前
|
NoSQL Redis C语言
|
2月前
|

22 0
|
2月前
|

Redis 数据结构+线程模型+持久化+内存淘汰+分布式
Redis 数据结构+线程模型+持久化+内存淘汰+分布式
301 0