Skip List的提出已有二十多年[Pugh, W. (1990)],却依旧应用广泛(Redis、LevelDB等)。作为平衡树(AVL、红黑树、伸展树、树堆)的替代方案,虽然它性能不如平衡树稳定,但是在实现难度上却很有优势。它的查询、插入、删除等主要操作时间复杂度也都是Θ(lgn),空间复杂度是Θ(n)。

一个Skip List的结构如下图,除了数据域,每个节点还包括1个或多个域用来保存后续节点的位置。

从结构上看,Skip List通过增加层数,节点上可以带有更多的信息,通过这些信息可以直接访问更远的节点(这 也是Skip List精髓所在),就像跳过去一样,所以取名叫Skip List(跳表)。

Skip List查询

查询操作很简单,比如我们要找图中节点key为20的节点。

  • 我们首先获取到头节点,从头检点的最高层开始(节点中的点表示指向节点的指针),下一个节点是17, 很明显20>17所以应该在后面。继续往后结果是NULL那说明后面没有要找的节点了。
  • 跳到下一层继续往后是2520<25说明后面也没有我们要找的节点了。
  • 再跳到下一层,往后就找到我们要的节点了。如果到最下面一层还找不到,那这个节点就肯定不在表中了(因为最低层包含所有节点)。

Skip List插入

插入操作稍微复杂, 首先我们要找到插入位置,怎么找我们刚才已经描述过了。如下图所示,插入key为10的节点,插入点应该是节点9和节点12之间(紫色的线表示要更新的指向)。然后是插入节点10,其实就是链表的逐层插入。

这里的需要注意是,逐层插入需要知道节点在每一层的位置,如在level-2中,节点10前面应该是头结点,而后面应该是节点17。 因为查询操作得到的只是最后位置,所以通常需要一个临时的空间来记录这些信息。如果节点的高度超过超过了Skip List的最大层数,那么Skip List的层数相应的需要升高。如节点10的高度是4的话,根据Skip List的结构特点,那么层数需要提高到level-3。

节点高度与Skip List的最大层数

理想的SkipList结构(如图一)是第一层有所有的节点,第二层只有1/2的节点,且是均匀间隔的,第三 层是1/4的节点,且是均匀间隔的...,那么理想的层数是lgnlgn。

每一次插入一个新节点时,最好的做法就是根据当前表的结构得到一个合适的高度,插入后可以让Skip List的尽量的接近理想的结构,但是实现上这会非常的复杂。

Pugh论文中提出的方法是根据概率随机为新节点生成一个高度,具体的算法如下:

  • 给定一个概率pp, 产生一个[0,1)[0,1) 之间的随机数
  • 如果这个随机数小于pp,则高度加11
  • 重复以上动作,直到随机数大于概率pp

虽然随机生成的高度会打破理想的结构,Pugh在论文中证明,这种结构依然有非常高概率可以使得时间复杂度为Θ(lgn)Θ(lgn)。

通常我们还会约束Skip List的最大层数,公式:maxLevel=log1/pnmaxLevel=log1/pn,其中n表示节点总数。 根据Pugh论文中的结论,p为1/2或者1/4时,整体性能会比较好。(当p=1/2时,确定节点高度有的地方称为抛硬币的方法)。

Skip List删除

删除操作跟插入操作类似。  

有兴趣可以看看Pugh论文!

转自:http://www.zkt.name/skip-list/

转载于:https://www.cnblogs.com/bonelee/p/6409146.html

图解Skip List——本质是空间换时间的数据结构,在lucene的倒排列表,bigtable,hbase,cassandra的memtable,redis中sorted set中均用到...相关推荐

  1. Cassandra 数据模型设计,根据你的查询来制定设计——反范式设计本质:空间换时间...

    转自:http://www.infoq.com/cn/articles/best-practice-of-cassandra-data-model-design 不要把Cassandra model想 ...

  2. FPGA之道(62)时空变换之空间换时间

    文章目录 前言 时空变换之空间换时间 缓存提速使用 模块复制 同频模块复制 缓存降频复制 缓存降频使用 逻辑拆分 流水线 流水线的由来 如何在组合逻辑中使用流水线 如何在时序逻辑中使用流水线 顺序系统 ...

  3. ie浏览器查看vue中js_浅析 Vue.js 中那些空间换时间的操作

    Hello,各位小伙伴,接下来的一段时间里,我会把我的课程<Vue.js 3.0 核心源码解析>中问题的答案陆续在我的公众号发布,由于课程的问题大多数都是开放性的问题,所以我的答案也不一定 ...

  4. leetcode-383-Ransom Note(以空间换时间)

    题目描述: Given an arbitrary ransom note string and another string containing letters from all the magaz ...

  5. 前端遍历导致查询数据时间过长_OLAP 服务器,空间换时间可行吗?

    [摘要] 全量预汇总真的是提高 OLAP 性能的可行方案吗?点击了解OLAP 服务器,空间换时间可行吗? 多维分析提供拖拽.旋转.切片.钻取等等人机交互操作,必须有秒级的响应速度.而这些操作对应的明细 ...

  6. 空间换时间,查表法的经典例子

    前言 上一篇分享了:C语言精华知识:表驱动法编程实践 这一篇再分享一个查表法经典的例子. 我们怎么衡量一个函数/代码块/算法的优劣呢?这需要从多个角度看待.本篇笔记我们先不考虑代码可读性.规范性.可移 ...

  7. [hashmap|空间换时间] leetcode 1 两数之和

    [hashmap|空间换时间] leetcode 1 两数之和 1.题目 题目链接 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下 ...

  8. 空间换时间--程序策略

    这几天修改一个去年做的程序,因为程序使用了xml保存的一些数据,整个xml文件结构欠佳,所以每次都需要对数据进行读取运算重新组合才能使用. 朋友需要这个程序多加点功能,于是顺便把这个去年做的不太好的地 ...

  9. 以空间换时间——动态规划算法及其应用:矩阵链相乘

    动态规划算法是5大算法基础中最重要的一个,它专门用来解决平面世界下的应用,即会多次使用二维数组. 当然动态规划算法是空间换时间的算法,也就是说:我们可以利用空间资源来使某算法问题的时间复杂度降到最低. ...

最新文章

  1. Python实现RGB和Lab颜色空间互转
  2. Hessian 原理分析
  3. 推荐系统User-Item Embedding图算法
  4. Spring AbstractBeanFactory
  5. mysql主从同步测试_mysql 主从同步测试
  6. Linux命令工作中常用的总结
  7. ASP.NET Core 企业级开发架构简介及框架汇总
  8. n个整数,其中有两个数是重复的,要求找出这两个重复的整数
  9. 策略模式/Strategy
  10. python的高阶函数
  11. 幻想乡三连A:五颜六色的幻想乡
  12. 【以太坊源码】mpt实现
  13. python自带的shell、其性能优于ipython吗_根据强化的性质和目的可以分成()。 A.自然强化物和人为的近似强化物B.积极强化和消极...
  14. 西蒙斯的赚钱秘籍:隐马尔科夫模型(HMM)的择时应用
  15. Docker学习总结(45)——Docker在沪江落地的实践
  16. 第十九周学习周报(20180709-20180715)
  17. DELL戴尔服务器Windows Server 2008/2012 操作系统安装指导-U盘安装
  18. 《计算机网络(计算机)》
  19. ps快捷图标在哪个文件夹_photoshop快捷键及快捷方式(详细)
  20. MySQL插入数据的多种方式

热门文章

  1. linux c/c++ 判断是否为中文(不包括中文符号,非正则)
  2. C++ 在线编译器(支持 C++11)
  3. linux变量inode,linux字符cdev和Inode的关系
  4. mysql dbcollat_Mysql Server 层混杂信息字典表 | 全方位认识 information_schem(四)
  5. java免安装工具包_Java1.8安装及环境变量配置
  6. 创建快捷方式命令_如何使用桌面快捷方式运行命令提示符命令
  7. git bash命令_?你可能不太会用的10个Git命令
  8. 计算机论文数据建模怎么写,如何撰写建模论文?
  9. php在用js_encode()转换时,实现斜杠不转义
  10. VScode+SSH Remote多级连跳配置