zoukankan      html  css  js  c++  java
  • 跳跃表的分析与实现

    ----《大规模分布式存储系统:原理解析与架构实战》读书笔记

    在了解了

    Bitcask存储模型后,又開始研究LSM树存储引擎。LSM在实现的过程中使用了一个非常有意思的数据结构:跳跃表。

    之前在《算法导论公开课》中听过这一节。当时感觉这样的结构和二叉树简直是殊途同归,可是一直没有亲自己主动手实现过。这次又遇到了。就来实现试试看。话说跳跃表和各种平衡树一样,都是用来加速查询的。要随手实现一个B树不easy,可是实现一个跳跃表就简单非常多。

    跳跃表的简介

    跳跃列表一个有序链表,按层建造的。底层是一个普通的有序链表。每一个更高层都充当以下列表的"高速跑道",查找一个元素时,能够先通过高层的“快车道”。在快车道上找不到时,从最接近目标元素的快车道逐步进入慢车道,直到最后找的目标元素。


    分析的时候。经常使用的形状例如以下:  


    各层是全然分开的列表。可是在实际实现中,则使用的为例如以下结构:


    这样的方式将多条联表的值合并到一起,同一时候使用指针来构造高层"快车道"。这样的方式管理起来简单。节省空间。

    更具体的介绍,请看跳表SkipList

    跳跃表的复杂度分析以及概率因子p

    来看看跳跃表的复杂度分析:

    • 空间复杂度: O(n) (期望)
    • 跳跃表高度: O(logn) (期望)

    相关操作的时间复杂度:

    • 查找: O(logn) (期望)
    • 插入: O(logn) (期望)
    • 删除: O(logn) (期望)

    跳跃表的操作时间负责度是基于概率的,全部加上了期望。


    在层 i 中的元素按某个固定的概率 p 出如今层 i+1 中。当p=1/2或者1/e的时候查找的性能最好。

    更具体的对照。请看到这篇文章:跳跃表。其中对不同概率的P对查询性能的影响做了对照。

    跳跃表的高度

    实际使用时。假设高度太高。会造成空间浪费。我们要做一个空间和时间的平衡。那么跳跃表的高度多少最合适?
    如果跳跃表中的元素个数为N,当跳跃表的高度为log(N)时,跳跃表进化为一个二叉树结构,其查询次数与二分查找法一致。这无疑最理想的结果。

    假设有一亿条记录,高度log(N)约等于30。redis中。最大高度也就是32。最多能够存几亿条记录。

    通常,我们用不了这么多记录。所以高度能够减少一点。

    跳跃表的实现

    跳跃表在levledb和redis中均有实现。

    二者都是用C实现的。我这个实现是C++版本号的

    主要特点为:

    • 支持模板
    • 0.2版本号添加了对迭代器和反向迭代器的支持
    • 可自己定义高度,默觉得8。0.2版本号版本号改为了16
      由于高度为8的话适合几百条的记录,这时候,选用跳跃表并没有太多优势,不如之间使用排序数组。将默认值改为16的话,能够方便几万条记录大小的地方使用。

    • 概率p:临时使用p=1/2
    • 做过单元測试,放心使用啦

    初始版本号简单直接。支持的函数为insert,find,remove。不支持范围操作。0.2版本号增了对了迭代器的支持。
    另外,在实现的时候也遇到一些问题,要注意模板编程与平时编程有所不同,平时编程通常实现和定义分离,分别放在.cpp和.h中。

    可是模板编程编写的一般是没有具现的实现。为了方便。一般定义和实现都会放在.h文件里。

    初始版本号简单直接,支持的函数为insert,find,remove。不再介绍。以下是0.2版本号实现的函数及其功能:
    void insert(const_value_type &value)
    在当前表中插入value值。值能够反复。
    void remove(const_value_type &value)
    删除第一个值为value的元素。

    反复值须要多次删除
    void clear()
    清空跳跃表
    iterator find(const_value_type &value)
    返回第一个值为value的元素的迭代器,否则返回end.
    iterator begin(int level = 0)
    返回指向当前表中第level层的第一个元素的迭代器。使用begin的时候,能够指定遍历不同的层。默觉得最底层。这个实际上并非标准的迭代器。为了实现分层遍历进行了特化。
    iterator end() const
    返回指向当前表中最后一个元素的迭代器。
    iterator rbegin() const
    返回指向当前表中最后一个元素的反向迭代器。
    iterator rend() const
    返回指向表中第一个元素的反向迭代器。
    unsigned long size()
    返回当前表中元素的数目
    unsigned int level()
    返回当前表的总层数
    unsigned int maxlevel()
    返回当前表的能使用的最大层数
    bool empty()
    推断表是否为空

    代码地址见上面的链接。


    欢迎光临我的站点----蝴蝶忽然的博客园----人既无名的专栏
    假设阅读本文过程中有不论什么问题,请联系作者,转载请注明出处。


  • 相关阅读:
    环保
    A股行情记录
    航运
    黑五类
    家电
    妖股
    高校概念股
    科技园区
    壳股
    白底黑字or黑底白字,眼睛更喜欢哪一个?
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6849184.html
Copyright © 2011-2022 走看看