SkipList 跳跃表
引子
考虑一个有序表:14->->34->->50->->66->72
从该有序表中搜索元素 < 23, 43, 59 > ,需要比较的次数分别为 < 2, 4, 6 >,总共比较的次数
为 2 + 4 + 6 = 12 次。有没有优化的算法吗? 链表是有序的,但不能使用二分查找。类似二叉
搜索树,我们把一些节点提取出来,作为索引。
这里我们把 < 14, 34, 50, 72 > 提取出来作为一级索引,这样搜索的时候就可以减少比较次数了。
我们还可以再从一级索引提取一些元素出来,作为二级索引,变成如下结构:

如果元素足够多,这种索引结构就能体现出优势来了。
跳跃表
跳表具有如下性质:
(1) 由很多层结构组成
(2) 每一层都是一个有序的链表
(3) 最底层(Level 1)的链表包含所有元素
(4) 如果一个元素出现在 Level i 的链表中,则它在 Level i 之下的链表也都会出现。
(5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。
其中 -1 表示 INT_MIN, 链表的最小值,1 表示 INT_MAX,链表的最大值。

跳跃表的搜索
例子:查找元素 117
(1) 比较 21, 比 21 大,往后面找
(2) 比较 37, 比 37大,比链表最大值小,从 37 的下面一层开始找
(3) 比较 71, 比 71 大,比链表最大值小,从 71 的下面一层开始找
(4) 比较 85, 比 85 大,从后面找
(5) 比较 117, 等于 117, 找到了节点。
跳跃表的插入
新节点和各层索引节点逐一比较,确定原链表的插入位置。O(logN)
把索引插入到原链表。O(1)
利用抛硬币的随机方式,决定新节点是否提升为上一级索引。结果为“正”则提升并继续抛硬币,结果为“负”则停止。O(logN)
总体上,跳跃表插入操作的时间复杂度是O(logN),而这种数据结构所占空间是2N,既空间复杂度是 O(N)。
跳跃表的删除
自上而下,查找第一次出现节点的索引,并逐层找到每一层对应的节点。O(logN)
删除每一层查找到的节点,如果该层只剩下1个节点,删除整个一层(原链表除外)。O(logN)
总体上,跳跃表删除操作的时间复杂度是O(logN)。
总结
跳跃表的优点在维持结构平衡的成本比较的,根据扔硬币,所以完全依靠随机。而二叉查找树在多次插入删除后,需要Rebalance来重新调整结构平衡。
SkipList 跳跃表的更多相关文章
- redis skiplist (跳跃表)
redis skiplist (跳跃表) 概述 redis skiplist 是有序的, 按照分值大小排序 节点中存储多个指向其他节点的指针 结构 zskiplist 结构 // 跳跃表 typede ...
- 小白也能看懂的Redis教学基础篇——朋友面试被Skiplist跳跃表拦住了
各位看官大大们,双节快乐 !!! 这是本系列博客的第二篇,主要讲的是Redis基础数据结构中ZSet(有序集合)底层实现之一的Skiplist跳跃表. 不知道那些是Redis基础数据结构的看官们,可以 ...
- 浅析SkipList跳跃表原理及代码实现
本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈“跳跃表”的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代 ...
- 【转】浅析SkipList跳跃表原理及代码实现
SkipList在Leveldb以及lucence中都广为使用,是比较高效的数据结构.由于它的代码以及原理实现的简单性,更为人们所接受.首先看看SkipList的定义,为什么叫跳跃表? "S ...
- 【Redis】skiplist跳跃表
有序集合Sorted Set zadd zadd用于向集合中添加元素并且可以设置分值,比如添加三门编程语言,分值分别为1.2.3: 127.0.0.1:6379> zadd language 1 ...
- 算法: skiplist 跳跃表代码实现和原理
SkipList在leveldb以及lucence中都广为使用,是比较高效的数据结构.由于它的代码以及原理实现的简单性,更为人们所接受. 所有操作均从上向下逐层查找,越上层一次next操作跨度越大.其 ...
- SkipList跳跃表(Java实现)
取自网络https://github.com/spratt/SkipList AbstractSortedSet.java package skiplist_m; /***************** ...
- 5分钟了解Redis的内部实现跳跃表(skiplist)
跳跃表简介 跳跃表(skiplist)是一个有序的数据结构,它通过在每个节点维护不同层次指向后续节点的指针,以达到快速访问指定节点的目的.跳跃表在查找指定节点时,平均时间复杂度为,最坏时间复杂度为O( ...
- 跳跃表Skip List的原理和实现
>>二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果 ...
随机推荐
- 【repost】一探前端开发中的JS调试技巧
有请提示:文中涉及较多Gif演示动画,移动端请尽量在Wifi环境中阅读 前言:调试技巧,在任何一项技术研发中都可谓是必不可少的技能.掌握各种调试技巧,必定能在工作中起到事半功倍的效果.譬如,快速定位问 ...
- eclipse/sublime 等宽字体设置
转载请注明出处:http://www.cnblogs.com/wubdut/p/4621889.html 使用ubuntu14.04会产生很多想日犬的地方.大家一般习惯于使用 eclipse 进行 j ...
- spring-aop代理的生效原理
主要说下spring里aop的生效的原理吧,并不是讲底层的cglib和gdk动态代理. 还是老一套的分析流程,先找到了aop的标签的handler,然后看下在解析这个标签的时候,都干了些什么,其实主要 ...
- poj 2488 A Knight's Journey
题目 题意:给出一个国际棋盘的大小 p*q,判断马能否不重复的走过所有格,并记录下其中按字典序排列的第一种路径. 因为要求字典序输出最小,所以按下图是搜索的次序搜素出来的就是最小的. 初始方向数组:i ...
- CocoaPods的使用(一) 安装
一.什么是CocoaPods? 前言: 思考如何引入一个第三方框架. 例如: 百度地图SDK.友盟.ShareSDK. 信鸽推送等. 从github或某处下载第三方SDK 工程中导入所需要的SDK的文 ...
- .Net 持续集成 —— windows service
上一篇讲了 Jenkins+WebDeploy+IIS完成 web项目部署,这篇继续讲windows service的部署. windows service 一般用于自动任务,定时完成某些操作.本文自 ...
- DevExpress中获取GridControl排序之后的List
public System.Collections.IList GetGridViewFilteredAndSortedData(DevExpress.XtraGrid.Views.Grid.Grid ...
- ASP.Net MVC OA项目笔记<三>
1.1.1 业务层和数据层之间加一个数据会话层,封装所有数据操作类实例的创建(工厂类) 工厂类是负责对象的创建 作用:将BLL和DAL解耦了,提供一个数据访问的统一访问点 数据会话层DBSession ...
- Asp.Net MVC EF之二:原生EF插入,更新数据的正确方法
引言 EF是相对与Dapper.NHibernate官方首推的ORM框架,其在开发过程中的方便,快捷毋庸置疑的,但由于EF本身的一些缓存机制.跟踪机制,所以在使用时有些地方需要特别注意. 下面我将自己 ...
- 手机app有了短信验证码还有没必要有图片验证码?
当然有必要,这里我们来聊一个恶意短信验证的案例,通过这个案例我们就能更好理解短信验证码和图片验证码这两者的关系了. 讨论防止恶意短信验证之前,我们先来看看什么是恶意短信验证及出现的原因. 恶意短信验证 ...