跳跃表(Skip Lists)是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。在大部分情况下,跳跃表的效率可以和平衡树相媲美,并且在实现上比平衡树要更为简单,因而得到了广泛的应用。

如上图所示,是一个跳跃表的示例。由此可以看出跳跃表的几个特点:

  • 有序性,如上图中各节点呈递增趋势;

  • 跳跃表由多个层组成;

  • 跳跃表的第一层始终包含所有元素;

  • 如果某个元素位于第 i 层,那该层一下的所有层也会包含此元素。

既然是链表的一种,那在实现时,固然要考虑插入、删除、查找等几个主要方法,下面来一一解析。

查找

要查找一个元素,应从顶层开始,自顶向下查找,又因为其有序性,因此与平衡树上的查找其实很类似。

以之前的图为例,要搜索 12,从顶层为入口,步骤大致如下:

  1. 从 L3 的第一个节点查询后一个节点 21,发现比 12 大,跳至下一层;

  2. 从 L2 的第一个节点查询后一个节点 9,比 12 小,因此继续向后;

  3. 继续查询 L2 的下一个节点 21,比 12 大,跳至下一层;

  4. 从 L1 的第一个节点开始查询,直至 17 时发现比 12 大,再次调至下一层;

  5. 从 L0 的第一个节点开始查询,最终发现 12 这个节点,查询结束。

如果要查询的节点在 L0 中都不存在,则应返回并告知“该节点不存在”。

插入

要插入一个节点,不难想象首先需要查询插入的位置,因此首先其实是类似的执行一次查询。然后视情况定是做替换操作还是新增节点。插入的时候要利用一个随机算法来获取该元素要插入的层高,并根据“如果某个元素位于第 i 层,那该层一下的所有层也会包含此元素”这一特性,在要插入层和以下层中都要插入这个新元素。最后还要注意维护层高。以下是插入过程的一个示例:

删除

删除的第一步和插入很类似,首先要执行查找过程。如果查找到,则将该元素删除。这里也必须注意“如果某个元素位于第 i 层,那该层一下的所有层也会包含此元素”这一特性。最后还要注意维护层高。

性能上,跳跃表支持平均 O(log N)、最坏 O(N) 复杂度的节点查找,还可以通过顺序性操作来批量处理节点。

代码实现在网上有很多代码可以参考,且实现方法和细节也不尽相同,因此不在这里提及,而是更多的关注原理。有时候掌握基础与原理其实更为重要。

本文的插图来自于 William Pugh 关于跳跃表的论文《Skip Lists: A Probabilistic Alternative to Balanced Trees》,其中分析了跳跃表的实现及性能,值得研读。

——————————

推荐阅读:

说框架设计思路

老王说架构

一次性讲透Activiti工作流

FaaS技术架构

华为Java编程军规,每季度代码验收标准

讲讲跳跃表(Skip Lists)的更多相关文章

  1. 跳跃表Skip List的原理和实现

    >>二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果 ...

  2. 数据结构与算法(c++)——跳跃表(skip list)

    今天要介绍一个这样的数据结构: 单向链接 有序保存 支持添加.删除和检索操作 链表的元素查询接近线性时间 ——跳跃表 Skip List 一.普通链表 对于普通链接来说,越靠前的节点检索的时间花费越低 ...

  3. 跳跃表Skip List的原理

    1.二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果需要的是一个 ...

  4. 跳跃表Skip List【附java实现】

    skip list的原理 Java中的LinkedList是一种常见的链表结构,这种结构支持O(1)的随机插入及随机删除, 但它的查找复杂度比较糟糕,为O(n). 假如我们有一个有序链表如下,如果我们 ...

  5. 用golang实现常用算法与数据结构——跳跃表(Skip list)

    背景 最近在学习 redis,看到redis中使用 了skip list.在网上搜索了一下发现用 golang 实现的 skip list 寥寥无几,性能和并发性也不是特别好,于是决定自己造一个并发安 ...

  6. Redis(2)——跳跃表

    一.跳跃表简介 跳跃表(skiplist)是一种随机化的数据结构,由 William Pugh 在论文<Skip lists: a probabilistic alternative to ba ...

  7. skip跳跃表的实现

    skiplist介绍 跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义, 跳表是由William Pugh发明的, ...

  8. skip list跳跃表实现

    跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入.删除.查找的复杂度均为O(logN).跳表的具体定义,跳表是由William Pugh发明的,这位确实是个大牛,搞出一 ...

  9. Skip List(跳跃表)原理详解与实现【转】

    转自:http://dsqiu.iteye.com/blog/1705530 Skip List(跳跃表)原理详解与实现 本文内容框架: §1 Skip List 介绍 §2 Skip List 定义 ...

随机推荐

  1. Android找回密码功能 手机找回、邮箱找回

    找回密码功能设计:https://blog.csdn.net/qq_33472765/article/details/82287404?utm_source=blogxgwz0 手机找回:https: ...

  2. hibernate的session的增删查改

    一.增 //******************增加****************** Customer c = new Customer(); c.setCust_name("阿里云&q ...

  3. 访问不了虚拟机 ubuntu中的myql,解决方案

    ============================================================== 1. 现象 2. 原因分析 2.1 访问虚拟机中的mysql的前提: 你的 ...

  4. 几个比较常用的jar包

    implementation 'com.android.support:recyclerview-v7:26+'implementation 'org.greenrobot:eventbus:3.1. ...

  5. 谈一谈从 Delphi 2009 之后就支援的重要功能 – 泛型 (Generic)

    前言 在C++的语言基础当中,除了物件导向.事件驱动的概念之外,模版设计(Template)也是非常重要的一环.然而,C++的开发人员能够善用模版设计的并不多.模版设计这个好物,一般还有一个名称,就是 ...

  6. [Swift]LeetCode94. 二叉树的中序遍历 | Binary Tree Inorder Traversal

    Given a binary tree, return the inorder traversal of its nodes' values. Example: Input: [1,null,2,3] ...

  7. [Swift]LeetCode419. 甲板上的战舰 | Battleships in a Board

    Given an 2D board, count how many battleships are in it. The battleships are represented with 'X's, ...

  8. [Swift]LeetCode838. 推多米诺 | Push Dominoes

    There are N dominoes in a line, and we place each domino vertically upright. In the beginning, we si ...

  9. [Swift]LeetCode1029. 两地调度 | Two City Scheduling

    There are 2N people a company is planning to interview. The cost of flying the i-th person to city A ...

  10. 注解式controller开发,action找不到controller???

    Spring这一列列的 ,  配置是真的多,学完我都忘啦  那个配置是干什么的了. 这里我遇到的问题是  我前台 使用action请求controller中的方法时,却找不到 报错404. 首先你路径 ...