图解Skip List——本质是空间换时间的数据结构,在lucene的倒排列表,bigtable,hbase,cassandra的memtable,redis中sorted set中均用到...
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
那说明后面没有要找的节点了。 - 跳到下一层继续往后是
25
且20<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中均用到...相关推荐
- Cassandra 数据模型设计,根据你的查询来制定设计——反范式设计本质:空间换时间...
转自:http://www.infoq.com/cn/articles/best-practice-of-cassandra-data-model-design 不要把Cassandra model想 ...
- FPGA之道(62)时空变换之空间换时间
文章目录 前言 时空变换之空间换时间 缓存提速使用 模块复制 同频模块复制 缓存降频复制 缓存降频使用 逻辑拆分 流水线 流水线的由来 如何在组合逻辑中使用流水线 如何在时序逻辑中使用流水线 顺序系统 ...
- ie浏览器查看vue中js_浅析 Vue.js 中那些空间换时间的操作
Hello,各位小伙伴,接下来的一段时间里,我会把我的课程<Vue.js 3.0 核心源码解析>中问题的答案陆续在我的公众号发布,由于课程的问题大多数都是开放性的问题,所以我的答案也不一定 ...
- leetcode-383-Ransom Note(以空间换时间)
题目描述: Given an arbitrary ransom note string and another string containing letters from all the magaz ...
- 前端遍历导致查询数据时间过长_OLAP 服务器,空间换时间可行吗?
[摘要] 全量预汇总真的是提高 OLAP 性能的可行方案吗?点击了解OLAP 服务器,空间换时间可行吗? 多维分析提供拖拽.旋转.切片.钻取等等人机交互操作,必须有秒级的响应速度.而这些操作对应的明细 ...
- 空间换时间,查表法的经典例子
前言 上一篇分享了:C语言精华知识:表驱动法编程实践 这一篇再分享一个查表法经典的例子. 我们怎么衡量一个函数/代码块/算法的优劣呢?这需要从多个角度看待.本篇笔记我们先不考虑代码可读性.规范性.可移 ...
- [hashmap|空间换时间] leetcode 1 两数之和
[hashmap|空间换时间] leetcode 1 两数之和 1.题目 题目链接 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下 ...
- 空间换时间--程序策略
这几天修改一个去年做的程序,因为程序使用了xml保存的一些数据,整个xml文件结构欠佳,所以每次都需要对数据进行读取运算重新组合才能使用. 朋友需要这个程序多加点功能,于是顺便把这个去年做的不太好的地 ...
- 以空间换时间——动态规划算法及其应用:矩阵链相乘
动态规划算法是5大算法基础中最重要的一个,它专门用来解决平面世界下的应用,即会多次使用二维数组. 当然动态规划算法是空间换时间的算法,也就是说:我们可以利用空间资源来使某算法问题的时间复杂度降到最低. ...
最新文章
- Python实现RGB和Lab颜色空间互转
- Hessian 原理分析
- 推荐系统User-Item Embedding图算法
- Spring AbstractBeanFactory
- mysql主从同步测试_mysql 主从同步测试
- Linux命令工作中常用的总结
- ASP.NET Core 企业级开发架构简介及框架汇总
- n个整数,其中有两个数是重复的,要求找出这两个重复的整数
- 策略模式/Strategy
- python的高阶函数
- 幻想乡三连A:五颜六色的幻想乡
- 【以太坊源码】mpt实现
- python自带的shell、其性能优于ipython吗_根据强化的性质和目的可以分成()。 A.自然强化物和人为的近似强化物B.积极强化和消极...
- 西蒙斯的赚钱秘籍:隐马尔科夫模型(HMM)的择时应用
- Docker学习总结(45)——Docker在沪江落地的实践
- 第十九周学习周报(20180709-20180715)
- DELL戴尔服务器Windows Server 2008/2012 操作系统安装指导-U盘安装
- 《计算机网络(计算机)》
- ps快捷图标在哪个文件夹_photoshop快捷键及快捷方式(详细)
- MySQL插入数据的多种方式
热门文章
- linux c/c++ 判断是否为中文(不包括中文符号,非正则)
- C++ 在线编译器(支持 C++11)
- linux变量inode,linux字符cdev和Inode的关系
- mysql dbcollat_Mysql Server 层混杂信息字典表 | 全方位认识 information_schem(四)
- java免安装工具包_Java1.8安装及环境变量配置
- 创建快捷方式命令_如何使用桌面快捷方式运行命令提示符命令
- git bash命令_?你可能不太会用的10个Git命令
- 计算机论文数据建模怎么写,如何撰写建模论文?
- php在用js_encode()转换时,实现斜杠不转义
- VScode+SSH Remote多级连跳配置