2018年12月30日12:26:04 我扑在跳表上,前后反复研究了十几二十次,一直都理解不了(大脑拒绝理解,停机)。昨晚下定决心(总结以前和现在学到的所有信息),拆分逻辑块,过滤这阶段不需要的信息,终于能理解跳表的基本结构了。
看源码有个小技巧(我的),不从main为入口,而是以model(模型)为逻辑块。
(1)先理解整体的zskiplist,哦,这个其实跟普通的链表是一样的,有header、有tail,还有长度;
(2)然后是结点Node;
(3)然后接下来要看的是model的CRUD,数据怎么生成、怎么删除。
而在看跳表插入结点Node时,先看理解zskiplistNode的ele+score+level,脑子里自动屏蔽span,因为跳表Node实际需要的是数据ele+score,还有层级level。
ele好理解吧?就是文字,而score就是评分。然后支撑起跳表层级的就是level。那为什么要将span放在最后呢?zslInsert插入跳表结点时,有50%~60%的代码都是讲span,完全混淆了我们看代码的顺序,把span相关的代码删掉后,你会发现很容易理解跳表。。马丹
/* Insert a new node in the skiplist. Assumes the element does not already
* exist (up to the caller to enforce that). The skiplist takes ownership
* of the passed SDS string 'ele'. */
zskiplistNode *zslInsert(zskiplist *zsl, double score, sds ele) {
zskiplistNode *update[ZSKIPLIST_MAXLEVEL], *x;
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[i] = i == (zsl->level-1) ? 0 : rank[i+1];
while (x->level[i].forward &&
(x->level[i].forward->score < score