zoukankan      html  css  js  c++  java
  • 第五章 跳跃表

    跳跃表 在每个节点维持多个指向其他节点的指针,达到快速访问节点的目的。Redis使用跳跃表作为有序集合键的底层实现之一。

    5.1 跳跃表的实现

      redis.h/zskiplistNode表示跳跃表节点。redis.h/zskiplist保存跳跃表节点的相关信息:节点数量、指向表头表尾节点的指针等。

      

      zskiplist结构

    • header:指向跳跃表的表头节点
    • tail:指向跳跃表的表尾节点
    • level:记录目前跳跃表内,层数最大的那个节点层数(表头节点的层数不计算在内)
    • length:表中节点的数量,不包含表头 

      zskiplistNode结构

    • level:用L1、L2....表示层。每层带有两个属性:前进指针和跨度。前进指针指向了一个可以访问的节点,跨度记录了当前节点和下一个可访问节点的距离。层数越多,访问其他节点就越快
    • backward指针:指向前一个节点,从表尾向表头遍历时使用
    • score:记录该节点代表的分值,如图中的1.0,2.0,3.0,所有节点按照分值从小到大排列
    • obj:各个节点保存的成员对象,如图中o1,o2,o3

      5.1.1 跳跃表节点

    type struct zskiplistNode{
    
        //后退指针
        struct zskiplistNode *backward;
    
        //分值
        double score;
    
        //成员对象
        obj *obj;
    
        //
        struct zskiplistLevel{
    
            //前进指针
            struct zskiplistNode *forward;
    
            //跨度
            unsigned int span;
         }  level[];
    
    }zskiplistNode;

      1. 层

      跳表节点的level数组包含多个元素,每个元素代表一层。层数大小在1~32之间随机生成。

      2. 前进指针

      通过每层的前进指针(level[i].forward)遍历整个调整的节点,直到遇到NULL。

      3. 跨度

      层的跨度(level[i].span)记录了该层指向的下一个节点的距离。指向NULL的层的跨度为0。在遍历的过程,记录访问路径上每个层数的跨度,当到达目的节点时,累加得到的跨度就是目的节点在跳跃表中的排位。

      4. 后退指针

      每个节点只有一个后退节点

      5. 分值和成员

      节点的分值(score属性)是一个double类型的浮点数,节点按照各自的分值从小到大排列

      节点的成员对象(obj属性)是一个指针,它指向一个字符串对象,而字符串对象存放着一个SDS值

      节点的分值可以相同,但成员对象必须唯一。当分值相同时,根据保存的字符串对象在字典中的顺序排序。

      5.1.2 跳跃表

      zskiplist是为了更方便的操作跳跃表,其中包含了可以访问跳表表头和跳表表尾的指针,或是快速获取跳表节点的数量。 

    5.2 跳跃表查找的时间复杂度以及跳跃表和红黑树的区别

      查找时间复杂度为O(logN),根红黑树一致。区别是红黑树维护平衡需要旋转,操作复杂,而跳表设计简单,但需要更多的存储空间。

    5.3 跳跃表插入和删除操作流程

      5.3.1 插入流程

      新节点从最高层开始逐层向下比较寻找,确定插入位置,复杂度O(logN)

      将索引插入到原链表,复杂度O(1)

      利用抛硬币的随机方式,决定新节点是否提升到上一级索引。若为正,新节点层数加一,并继续尝试,直到为负。时间复杂度为O(logN),但是Redis中限制了层数最多32,应该是O(1)

      假设节点每层节点数是上一层的k倍,那么总节点数计算如下公式。比如当k为2时,总结点数为2N。这也说明了跳跃表,是一种用空间换时间的设计思路,相对于红黑树来说,操作简单,但需要的存储空间更多。

      

      5.3.2 删除流程

      从最高层向下比较寻找,找到节点后,删除节点,删除节点每层的时候,需要将前节点的当前层指针指向后节点的当前层,即注意维护层之间的指针关系。

    参考:

    关于跳跃表的一点理解  

    人生就像蒲公英,看似自由,其实身不由己。
  • 相关阅读:
    day10
    day 09
    day08
    day07
    day6
    day5
    成员变量和局部变量
    (第五章)java面向对象之this的作用总结
    简单的音乐播放
    异步消息处理机制 简析
  • 原文地址:https://www.cnblogs.com/walker993/p/14425990.html
Copyright © 2011-2022 走看看