/* ZSETs use a specialized version of Skiplists */typedefstructzskiplistNode{sdsele;doublescore;structzskiplistNode*backward;structzskiplistLevel{structzskiplistNode*forward;unsignedlongspan;}level[];}zskiplistNode;typedefstructzskiplist{structzskiplistNode*header,*tail;unsignedlonglength;intlevel;}zskiplist;
插入
先找到待插入的位置,查找的时候从顶层开始,在当前层尽可能的往前移动,每层都满足[header, update[i]]:(< score) or (== score and < ele))。最终的插入位置在update[i]之后。
zskiplistNode*zslInsert(zskiplist*zsl,doublescore,sdsele){zskiplistNode*update[ZSKIPLIST_MAXLEVEL],*x;unsignedintrank[ZSKIPLIST_MAXLEVEL];inti,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||(x->level[i].forward->score==score&&sdscmp(x->level[i].forward->ele,ele)<0))){rank[i]+=x->level[i].span;x=x->level[i].forward;}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();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 */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;elsezsl->tail=x;zsl->length++;returnx;}
intzslDelete(zskiplist*zsl,doublescore,sdsele,zskiplistNode**node){zskiplistNode*update[ZSKIPLIST_MAXLEVEL],*x;inti;x=zsl->header;for(i=zsl->level-1;i>=0;i--){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))){x=x->level[i].forward;}update[i]=x;}/* We may have multiple elements with the same score, what we need
* is to find the element with both the right score and object. */x=x->level[0].forward;if(x&&score==x->score&&sdscmp(x->ele,ele)==0){zslDeleteNode(zsl,x,update);if(!node)zslFreeNode(x);else*node=x;return1;}return0;/* not found */}