redis - 跳跃表详细介绍

    redis吸引不少人使用的一个重要的缘由,就是它对众多数据类型的支持。包括string,hash,set,zset,list等五种数据对象。redis

    其中zset用来保证数据的有序存储,实现中,redis使用跳跃表和压缩列表,做为zset的底层实现。当元素数量比较多,或者元素成员是比较长的字符串时,底层实现采用跳跃表。算法


    跳跃表是什么?数组

    一种有序的数据结构,经过在节点中维持多个指向其它节点的指针,达到快速访问的目的。数据结构

      

    跳跃表的好处是什么? ide

    1. 跟平衡树相比,实现简单;spa

    2. 平均复杂度为O(logN),最坏为O(N);指针

   

    跳跃表的数据结构由 zskiplistNode 和 zskiplist 两个结构定义,zskiplistNode表示跳跃表节点,zskiplist保存跳跃表节点的相关信息。对象

    

    zskiplistNode的数据结构以下:blog

   typedef struct zskiplistNode {排序

    robj *obj;

    double score;

    struct zskiplistNode *backward;

    struct zskiplistLevel {

        struct zskiplistNode *forward;

        unsigned int span;

     } level[];

   } zskiplistNode

    skiplistLevel包含多个元素,每一个元素包含一个指向其它节点的前进指针,经过它来加快访问其它节点。每次建立一个跳跃表节点的时候,会随机生成一个值,该值介于1和32之间,做为level数组的大小。span表示层的跨度,用来计算最终的位置,程序在遍历时,会将沿途访问过的全部层的跨度累计,得出目标节点的对应位置;

    backward用于从表尾向表头访问节点;

    score 全部节点都按照它进行排序;

    obj 指向一个字符串对象;


    zskiplist的数据结构:  

    typedef struct zskiplist {

       struct zskiplistNode *header, *tail;

       unsigned long length;

       int level;

    } zskiplist;

   header,tail用来表示跳跃表的表头和表尾巴节点,length表示跳跃表的总体长度,level表示跳跃表的高度。

   zskiplist的主要做用,是能够方便的对整个跳跃表进行处理,好比获取跳跃表的整个长度的信息。

 

   跳跃表的层数如何生成?

   在插入的过程当中构造,向跳跃表中插入一个数值,至关于在表中插入一列从起始跳跃表节点S出发,向上的一段数值,须要肯定两个元素:数值的位置和层数。因为全部链是递增序列的方式,因此位置主要是根据对应数值的比较对出。而层数,程序会先记录比该节点小的值的span,而后,随机生成介于1和32之间的数值,做为该节点的层数,该算法主要是基于冥次定律,越大的数出现的几率越小。假设level为2的几率为P,则level为3的几率为p*p,以此类推。


   跳跃表查找的示例图:

  

wKiom1RiVkqQnE8hAAE8Ajga6lE999.jpg

   图中,表示有三个节点,他们对应的score分别为1,2,3,其中,虚线,表明在跳跃表中,查找score为2,成员对象为02的节点,在查找过程当中,通过了两个span为1的节点,因此,能够得出该节点在跳跃表中的排位为2。 BW表示后退指针,实线的,表示节点间的span,因为节点间的关系比较多,因此只画了几个。

相关文章
相关标签/搜索