跳跃表Skip List【附java实现】
skip list的原理
Java中的LinkedList是一种常见的链表结构,这种结构支持O(1)的随机插入及随机删除, 但它的查找复杂度比较糟糕,为O(n)。
假如我们有一个有序链表如下,如果我们想找到值为59的节点,需要查找7次。怎么提高查询效率呢?通常的做法是使用二分法,但LinkedList的随机访问时间复杂度同样为O(n),因此朴素的二分法并不适用。那怎么办呢?

我们可以在节点中增加额外的跳跃节点,如下:

这样我们可以根据跳跃节点查询,只需要查找3次。至于查询47,我们先根据跳跃节点来查询,于是在节点22上,它的跳跃指针指向55,比47要大,因此我们可以知道47可能会存在于节点22和节点55之间,这时候再根据普通的指针顺序查找。一共需要查找5次。
随着节点的增多,我们的链表结构会变成这样:

跳跃节点的密度为普通节点的一半,理想情况下,这种结构会比原结构查询性能提高一倍。有没有办法再提高呢?有,我们可以在这基础上再加一层新的跳跃节点,这层节点的密度又为第一层跳跃节点的一半。

更直观点:

进一步限定每一层的跳跃节点都由它下一层的跳跃节点中产生,因此,我们的跳跃表最终看起来像是这样的。

我们不区分每一层是原节点还是跳跃节点,将最底下的那一层节点称为第一层节点,第一层节点上面为第二层节点,然后第三层...以此类推。
这样的结构,称之为跳跃表。假设每一层的节点数为下一层的一半,那么时间复杂度为O(logn)。
实现方案
如上所述,skip list是具有分层结构的有序链表,那每一层的节点应该如何产生呢?
我们可以在新增元素的时候使用随机方法决定这个元素有几层节点。设定该元素有且只有一层节点概率为1/2,有且只有两层节点概率为1/4,有且只有三层节点概率为1/8,以此类推。然后触发随机事件,当概率为1/2的事件发生时该元素有一层节点,概率为1/2的事件发生时该元素有两层节点...另外,我们限定一个跳跃表应该具有一个最大的层数限制。
假设一个跳跃表最大层数限制为4,那么可以设定一个整数区间为[1, 2^(4-1)],即[1, 8]。然后取一个1~8的随机数,当落在[5, 8]区间时有一层节点,落在[3, 4]区间时有两层节点,落在[2, 2]区间时有三层,落在[1, 1]上时有四层。由于我们设定了跳跃表的最大层数,因此概率等式1 = 1/2 + 1/4 + 1/8 + ... + 1/2^n的最后两项相同。
Java实现
跳跃表Skip List【附java实现】的更多相关文章
- 跳跃表Skip List的原理和实现
>>二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果 ...
- 跳跃表Skip List的原理
1.二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果需要的是一个 ...
- 数据结构与算法(c++)——跳跃表(skip list)
今天要介绍一个这样的数据结构: 单向链接 有序保存 支持添加.删除和检索操作 链表的元素查询接近线性时间 ——跳跃表 Skip List 一.普通链表 对于普通链接来说,越靠前的节点检索的时间花费越低 ...
- 用golang实现常用算法与数据结构——跳跃表(Skip list)
背景 最近在学习 redis,看到redis中使用 了skip list.在网上搜索了一下发现用 golang 实现的 skip list 寥寥无几,性能和并发性也不是特别好,于是决定自己造一个并发安 ...
- Redis(2)——跳跃表
一.跳跃表简介 跳跃表(skiplist)是一种随机化的数据结构,由 William Pugh 在论文<Skip lists: a probabilistic alternative to ba ...
- 讲讲跳跃表(Skip Lists)
跳跃表(Skip Lists)是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的.在大部分情况下,跳跃表的效率可以和平衡树相媲美,并且在实现上比平衡树要更为 ...
- skip跳跃表的实现
skiplist介绍 跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义, 跳表是由William Pugh发明的, ...
- skip list跳跃表实现
跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义,跳表是由William Pugh发明的,这位确实是个大牛,搞出一 ...
- 基于跳跃表的 ConcurrentSkipListMap 内部实现(Java 8)
我们知道 HashMap 是一种键值对形式的数据存储容器,但是它有一个缺点是,元素内部无序.由于它内部根据键的 hash 值取模表容量来得到元素的存储位置,所以整体上说 HashMap 是无序的一种容 ...
随机推荐
- 数据库导出导入操作(expdp,impdp)
EXPDP和IMPDP是服务端的工具程序,他们只能在ORACLE服务端使用,不能在客户端使用. 命令行: sqlplus/nolog connect username/password as sysd ...
- 如何清除xcode里面的mobileprovision文件
通过终端进行删除 首先cd到目录”~/Library/MobileDevice/Provisioning\ Profiles” cd ~/Library/MobileDevice/Provisioni ...
- css media
/* media */ /* 横屏 */ @media screen and (orientation:landscape){ } /* 竖屏 */ @media screen and (orient ...
- 24种设计模式--多例模式【Multition Pattern】
这种情况有没有?有!大点声,有没有?有,是,确实有,就出现在明朝,那三国期间的算不算,不算,各自称帝,各有各的地盘,国号不同.大家还 记得那首诗<石灰吟>吗?作者是谁?于谦,他是被谁杀死的 ...
- underscorejs-shuffle学习
2.21 shuffle 2.21.1 语法 _.shuffle(list) 2.21.2 说明 返回一个随机乱序的list副本数组, 使用 Fisher-Yates shuffle 来进行随机乱序. ...
- 利用set实现去重
最近读了一些有关于ES6的文章,觉得真是一个超级大的进步,就是不知道兼容性怎么样,鉴于我还在初学,先写个小例子练手,顺便时刻提醒自己要坚持学下去.未来的趋势肯定是替代es5没跑了. var arr=[ ...
- PHP框架_ThinkPHP基础
目录 1.ThinkPHP项目结构 2.ThinkPHP运行流程 3.ThinkPHP配置文件 4.ThinkPHP四种URL模式 5.ThinkPHP用户自定义函数 6.ThinkPHP模板展示及变 ...
- illegal mix of collcations表连接时非法的校对
背景:旧表导入新表,新表里的字段是字符串类型 新表是int类型 两个字段通过字符串处理后相等 (准备left join 关联起来)报错 把int类型字段更改成varchar字符串类型后成功
- 当INPUT 连续输入是连续触发
在 Web 开发中经常会碰到需要动态监听输入框值变化的情况,如果使用 onkeydown.onkeypress.onkeyup 这个几个键盘事件来监测的话,监听不了右键的复制.剪贴和粘贴这些操作,处理 ...
- YII Query Builder
今天遇到一个Query Builder 联合查询问题: 查询关联表某个字段的总数