讲讲跳跃表(Skip Lists)
跳跃表(Skip Lists)是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。在大部分情况下,跳跃表的效率可以和平衡树相媲美,并且在实现上比平衡树要更为简单,因而得到了广泛的应用。
如上图所示,是一个跳跃表的示例。由此可以看出跳跃表的几个特点:
有序性,如上图中各节点呈递增趋势;
跳跃表由多个层组成;
跳跃表的第一层始终包含所有元素;
如果某个元素位于第 i 层,那该层一下的所有层也会包含此元素。
既然是链表的一种,那在实现时,固然要考虑插入、删除、查找等几个主要方法,下面来一一解析。
查找
要查找一个元素,应从顶层开始,自顶向下查找,又因为其有序性,因此与平衡树上的查找其实很类似。
以之前的图为例,要搜索 12,从顶层为入口,步骤大致如下:
从 L3 的第一个节点查询后一个节点 21,发现比 12 大,跳至下一层;
从 L2 的第一个节点查询后一个节点 9,比 12 小,因此继续向后;
继续查询 L2 的下一个节点 21,比 12 大,跳至下一层;
从 L1 的第一个节点开始查询,直至 17 时发现比 12 大,再次调至下一层;
从 L0 的第一个节点开始查询,最终发现 12 这个节点,查询结束。
如果要查询的节点在 L0 中都不存在,则应返回并告知“该节点不存在”。
插入
要插入一个节点,不难想象首先需要查询插入的位置,因此首先其实是类似的执行一次查询。然后视情况定是做替换操作还是新增节点。插入的时候要利用一个随机算法来获取该元素要插入的层高,并根据“如果某个元素位于第 i 层,那该层一下的所有层也会包含此元素”这一特性,在要插入层和以下层中都要插入这个新元素。最后还要注意维护层高。以下是插入过程的一个示例:
删除
删除的第一步和插入很类似,首先要执行查找过程。如果查找到,则将该元素删除。这里也必须注意“如果某个元素位于第 i 层,那该层一下的所有层也会包含此元素”这一特性。最后还要注意维护层高。
性能上,跳跃表支持平均 O(log N)、最坏 O(N) 复杂度的节点查找,还可以通过顺序性操作来批量处理节点。
代码实现在网上有很多代码可以参考,且实现方法和细节也不尽相同,因此不在这里提及,而是更多的关注原理。有时候掌握基础与原理其实更为重要。
本文的插图来自于 William Pugh 关于跳跃表的论文《Skip Lists: A Probabilistic Alternative to Balanced Trees》,其中分析了跳跃表的实现及性能,值得研读。
——————————
推荐阅读:
讲讲跳跃表(Skip Lists)的更多相关文章
- 跳跃表Skip List的原理和实现
>>二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果 ...
- 数据结构与算法(c++)——跳跃表(skip list)
今天要介绍一个这样的数据结构: 单向链接 有序保存 支持添加.删除和检索操作 链表的元素查询接近线性时间 ——跳跃表 Skip List 一.普通链表 对于普通链接来说,越靠前的节点检索的时间花费越低 ...
- 跳跃表Skip List的原理
1.二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果需要的是一个 ...
- 跳跃表Skip List【附java实现】
skip list的原理 Java中的LinkedList是一种常见的链表结构,这种结构支持O(1)的随机插入及随机删除, 但它的查找复杂度比较糟糕,为O(n). 假如我们有一个有序链表如下,如果我们 ...
- 用golang实现常用算法与数据结构——跳跃表(Skip list)
背景 最近在学习 redis,看到redis中使用 了skip list.在网上搜索了一下发现用 golang 实现的 skip list 寥寥无几,性能和并发性也不是特别好,于是决定自己造一个并发安 ...
- Redis(2)——跳跃表
一.跳跃表简介 跳跃表(skiplist)是一种随机化的数据结构,由 William Pugh 在论文<Skip lists: a probabilistic alternative to ba ...
- skip跳跃表的实现
skiplist介绍 跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义, 跳表是由William Pugh发明的, ...
- skip list跳跃表实现
跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义,跳表是由William Pugh发明的,这位确实是个大牛,搞出一 ...
- Skip List(跳跃表)原理详解与实现【转】
转自:http://dsqiu.iteye.com/blog/1705530 Skip List(跳跃表)原理详解与实现 本文内容框架: §1 Skip List 介绍 §2 Skip List 定义 ...
随机推荐
- [Swift]LeetCode468. 验证IP地址 | Validate IP Address
Write a function to check whether an input string is a valid IPv4 address or IPv6 address or neither ...
- linux入门--Linux发行版本详解
从技术上来说,李纳斯•托瓦兹开发的 Linux 只是一个内核.内核指的是一个提供设备驱动.文件系统.进程管理.网络通信等功能的系统软件,内核并不是一套完整的操作系统,它只是操作系统的核心.一些组织或厂 ...
- linux入门--Linux系统的优缺点
1) 大量的可用软件及免费软件 Linux 系统上有着大量的可用软件,且绝大多数是免费的,比如声名赫赫的 Apache.Samba.PHP.MySQL 等,构建成本低廉,是 Linux 被众多企业青睐 ...
- Vmware安装Ubuntu ==> 连网成功
由于工作需要,得把NS3安装到内网服务器中,大家知道这个是不能连接外网的,学校又没有Ubuntu高校源.NS3要先安装一大堆的依赖,让人头痛的是在内网里有没发以终端指令形式安装,针对这种麻烦,找到两个 ...
- Python文本数据互相转换(pandas and win32com)
(工作之后,就让自己的身心都去休息吧) 今天介绍一下文本数据的提取和转换,这里主要实例的转换为excel文件(.xlsx)转换world文件(.doc/docx),同时需要使用win32api,同py ...
- mongo 删除 表中字段
查询语句 db.getCollection("A表").update( { } ,{ $unset:{"a":1} } , {multi: true} ) ...
- 【Spark篇】---SparkStream初始与应用
一.前述 SparkStreaming是流式处理框架,是Spark API的扩展,支持可扩展.高吞吐量.容错的实时数据流处理,实时数据的来源可以是:Kafka, Flume, Twitter, Zer ...
- MVC中的下载文件及上传
前言:最近做的项目中用到了文件下载与上传,一下子想不起来,只能进行百度,为了方便自己做了一个小demo,特此写了这篇小笔记 1.页面方面: 2.控制器方面 namespace MvcUpload.Co ...
- 并发编程(一)—— volatile关键字和 atomic包
本文将讲解volatile关键字和 atomic包,为什么放到一起讲呢,主要是因为这两个可以解决并发编程中的原子性.可见性.有序性,让我们一起来看看吧. Java内存模型 JMM(java内存模型) ...
- C#版(击败100.00%的提交) - Leetcode 744. 寻找比目标字母大的最小字母 - 题解
C#版 - Leetcode 744. 寻找比目标字母大的最小字母 - 题解 744.Find Smallest Letter Greater Than Target 在线提交: https://le ...