redis源码之:跳跃表skiplist

老规矩,先来看看大致结构:
redis源码之:跳跃表skiplist_第1张图片

debug所用demo如下:

#include "src/server.h"

void testSDS();
void testAlign();
void testZipList();
void testSkipList();
void testQuickList();

int main(int argc, char **argv) {
//    testAlign();
//    testSDS();
//    testZipList();
//    testQuickList();
    testSkipList();
}

void testSkipList(){
    zskiplist *my_list = zslCreate();
    sds sds01 = sdsnew("0001a");
    sds sds02 = sdsnew("0002a");
    sds sds03 = sdsnew("0003a");
    sds sds04 = sdsnew("0004a");
    sds sds05 = sdsnew("0005a");
    zslInsert(my_list,1,sds01);
    zslInsert(my_list,2,sds02);
    zslInsert(my_list,3,sds03);
    zslInsert(my_list,4,sds04);
    zslInsert(my_list,5,sds05);
    
}

skiplist本质是有序的链表,每个节点可能会属于多层,至少属于一层,是个典型的以空间换时间的结果,大致的数据结构如下:

typedef struct zskiplistNode {//skiplist节点
    sds ele;              //节点字符串内容
    double score;         //节点分值,主要用于插入排序比对
    struct zskiplistNode *backward; //除了header节点和header后的一个节点,其余节点的backward都指向前面节点
    struct zskiplistLevel {  
        struct zskiplistNode *forward;//当前节点在当前层,指向的下一个节点
        unsigned long span; //到下一个节点间隔多少个元素,即步长。
    } level[];  //每个节点都可能属于多层
} zskiplistNode;

typedef struct zskiplist {
    struct zskiplistNode *header, *tail;//定义头结点和尾节点
    unsigned long length; //node节点数量
    int level; //当前list用了多少层
} zskiplist;

从上图可以看出:
level0:header-》node0-》node1-》node2->node3
level1和level2都是:header-》node0->node2

一、创建skiplist并初始化
redis源码之:跳跃表skiplist_第2张图片

二、节点插入
节点插入是构建skiplist最核心的逻辑,主要调用zslInsert()方法:

关于level的生成:

int zslRandomLevel(void) {
  int level = 1;
  //0-65535 <0.25*65535的概率
   while ((random()&0xFFFF) < (ZSKIPLIST_P * 0xFFFF))
       level += 1;//每次加一的概率为0.25
   return (level<ZSKIPLIST_MAXLEVEL) ? level : ZSKIPLIST_MAXLEVEL;
}

那么为1的概率:1-0.25
大于1的概率:0.25
为2的概率:0.25*(1-0.25)
为3的概率:0.25* 0.25*(1-0.25)
为n的概率:0.25^n-1 * (1-0.25),
n最大为32

delete和update相对没什么新的技术点,这里就不做更深入研究了。

与红黑树对比有何优势劣势:
同二分查找,红黑树和跳跃表的时间复杂度都能达到Olog(n).,但跳跃表实现上更加简单易懂;
跳跃表牺牲一定的空间用于层级管理,但是层级中只是保存了节点指针,相对而言,空间的牺牲较小;
跳跃表的插入删除影响的局部范围小并发能力强,红黑树可能会涉及树的旋转调整,影响较大;
跳跃表可以很方便通过层级节点定位实现范围查找;

Redis源码剖析之跳表(skiplist)
【Redis】skiplist跳跃表
Skiplist论文原地址

你可能感兴趣的:(redis源码学习分析,redis,skiplist,java)