跳跃表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 是无序的一种容 ...
随机推荐
- Signalr简单入门,使用注意点
注意点:1,创建proxy代理时候,继承了hub的类,方法名在js中,同名,但是默认首字母是小写,2,js中代理毁掉方法的名称和继承了hub的类的方法中的Clients.All.的对象名称要一致(名称 ...
- EntityFrameowk6.1 使用enum和低版本的不同
原有项目中使用EF5.0 实体类 public partial class Log : BaseEntity { public Nullable<int> LogLevelId { get ...
- 复制构造函数2——深入理解
//如果不显示定义复制构造函数,编译会出错,原因是:在创建对象s2时,调用默认复制构造函数并用对象s1对其进行初始化,致使s2中指针 //与s1中指针指向同一储存空间,当一个对象生命周期结束后调用析构 ...
- 主成份分析PCA
Data Mining 主成分分析PCA 降维的必要性 1.多重共线性--预测变量之间相互关联.多重共线性会导致解空间的不稳定,从而可能导致结果的不连贯. 2.高维空间本身具有稀疏性.一维正态分布有6 ...
- 【SPOJ839】最优标号
[题目描述] 给你一张无向图G(V,E).每个顶点都有一个标号,它是一个[0,2^31-1]内的整数.不同的顶点可能会有相同的标号. 对每条边(u,v),我们定义其费用cost(u,v)为u的标号与v ...
- python使用VBA:Excel创建图表(转)
# -*- coding: utf-8 -*- """ Created on Thu Mar 06 11:22:03 2014 @author: Administrato ...
- 寒假挑战PythonTip(一人一python)总结——算法是程序的灵魂,程序员的心法
2014年2月中旬,我上升到挑战python英雄榜第3名.这是我寒假修炼算法的成果之一.来一下总结吧! Linux的创始人Linus Torvalds在一次演讲中有一段涉及“什么才是优秀程序员 ...
- 如何参与github上的开源项目
今晚比较闲,于是乎装修了一下博客,顺便将一块心病(怎么参加github上的开源项目)解决了,最后发个文章总结下 这些是参考的链接 http://blog.csdn.net/five3/article/ ...
- PHP面向对象(OOP):__set(),__get(),__isset(),__unset()四个方法的应用
一般来说,总是把类的属性定义为private,这更符合现实的逻辑.但是, 对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数”__get()”和”__set()”来获取和赋值其属性 ...
- html5 DeviceOrientation来实现手机网站上的摇一摇功能
原文地址:http://www.cootm.com/?p=706 从网上转载看到的,感觉不错,就转过来了,特此感谢 cnblogs 的 幸福2胖纸的码农生活,直接转载了,不要介意!呵呵 以下是转载内容 ...