跳跃表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 是无序的一种容 ...
随机推荐
- 算法的优化(C语言描述)
算法的优化 算法的优化分为全局优化和局部优化两个层次.全局优化也称为结构优化,主要是从基本控制结构优化.算法.数据结构的选择上考虑:局部优化即为代码优化,包括使用尽量小的数据类型.优化表达式.优化赋值 ...
- 用eval 动态编译代码
eval 有另外一种用法, 其参数是作为一个字串表达式, 而不是代码块.在运行时, 它将字串临时编译成代码并且执行. 这很易用, 但也很危险, 因为有可能会把具有危害性的代码放到字串里. foreac ...
- C++ 语法规则
C++ 中的布尔类型:布尔类型只占用一个bit ,但是如果连续定义多个布尔类型时,编译器可能会多个布尔类型定义在一起.true 编译器用1来表示.false 编译器用0来表示. 将一个其他类型的数 ...
- html的input输入框提示信息 点击隐藏
<input type="text" <!-- 文本框 --> name="textfield" value="请输入...& ...
- 在vs code中使用ftp-sync插件实现客户端与服务器端代码的同步
在vs code中使用ftp-sync插件实现客户端与服务器端代码的同步 下载安装 vscode-ftp-sync 插件. 安装方法1. Ctrl+Shift+P 输入 ext install [插件 ...
- FileReader上传图片
实现拖拽图片,在上传至服务器前,显示图片并操控大小 利用HTML5 dragenter dragover dragleave drop 在实现图片显示方面,用了FileReader这个类 var fi ...
- 【转】ThinkPHP中数据库操作返回值总结
Thinkphp中的Think\Model类提供了数据库的基本CURD(Create.Update.Read及Delete),通过该类可以很便捷的进行操作.Model类及扩展类主要的方法有: Crea ...
- opencv之图像腐蚀
最近准备好好学习opencv 这博客就是我的学习笔记. #include <cv.h> #include <highgui.h> using namespace std; vo ...
- 一些CMS网站系统漏洞,练手用(持续更新)
仅供拿shell,提权测试用,请勿恶意破坏 XuSoft系统: 后台万能密码:'or'='or' 可直接登陆,后台地址 /manage/login.asp inurl:ReadArticlemb.a ...
- Python爬虫第一步
这只是记录一下自己学习爬虫的过程,可能少了些章法.我使用过的是Python3.x版本,IDE为Pycharm. 这里贴出代码集合,这一份代码也是以防自己以后忘记了什么,方便查阅. import req ...