数据结构笔记之跳表(SkipList)
一、跳表简述
跳表可以看做是一个带有索引的链表,在介绍跳表之前先看一下一个普通的链表,假如当前维护了一个有序的链表:
现在要在这个链表中查找128,因为事先不知道链表中数值的分布情况,我们只能从前到后依次遍历,那么有没有什么取巧的方法呢?
如果我们能够存储下最中间节点的引用,比如存储节点29的引用,然后每次要查找节点的时候就先跟29比较一下,如果比29小就还是从前往后找(因为不会超过中间节点,从前往后和从中间往前区别不大),如果比29大就直接跳到29开始往后找,这种思想就是为链表添加了一个简单的索引,一下可以节省掉一半的查找时间。跳表的设计思想类似,通过为链表的每个节点设置高度来添加索引,不同的高度称为不同的层,每一层的next只能指向当前层的下一个节点,下面是一个跳表的示例:
最左面一列null为head节点,用于保存每一层的第一个节点,在查找的时候先从最高层开始查找,比如要在上面的跳表中查找128:
首先取最高层第六层的next,是47,比128小,直接跳到47,然后47的第六层的next是null,说明到了最后一个了,层数减少,47的第五层的next是255,比128大,也不行,继续减少层数,47的第四层的next是255,依然比128大,继续减少层数,47的第三层的next是128,get it!
看上面的过程有没有意识到一个问题,就是如果跳表的层数过多的话”比较-降层“这个过程就会有不少的浪费,比如上面的在47这个节点进行了4次比较才找到了有效的next节点,如果这个值再大一点的话就会退化得很严重。那么这个层是如何来的呢,跳表的高度是通过一个随机数决定的,初始时默认为一层,然后一直产生随机数只要小于0.5就将层数加一层继续随机,但是随机这种东西毕竟是不可控的,为了避免出现过高的层数最好还是设置一个最大层数以免某些节点的层数过大。
二、跳表的实现
跳表的简单Java实现:
SkipList.java:
package alg.link;import org.apache.commons.lang3.StringUtils;/*** 跳表结构的简单Java实现** @author CC11001100*/
public class SkipList<T extends Comparable<T>> {private static final double DEFAULT_CONTINUE_INCREMENT_LEVEL_THRESHOLD = 0.75;private static final int DEFAULT_MAX_LEVEL = 10;// 用于控制层数,决定层数时当随机数小于此值时会一直升层直到最大,取值范围[0, 1],值越大越可能得到高层数,此值设置不当很有可能退化成链表private double continueIncrementLevelThreshold;// 为了防止随机数出现异常情况过高,对最大层数做一个限制private int maxLevel;// 链表的头结点,每一层的头都保存在这里private Node<T> head;public SkipList() {this(DEFAULT_CONTINUE_INCREMENT_LEVEL_THRESHOLD, DEFAULT_MAX_LEVEL);}public SkipList(double threshold) {this(threshold, DEFAULT_MAX_LEVEL);}public SkipList(double threshold, int maxLevel) {this.continueIncrementLevelThreshold = threshold;this.maxLevel = maxLevel;this.head = new Node<>(null, 0);// 初始化时就将其扩充到最大避免后面扩容增加复杂性,只有head会浪费一些空间其它节点都是有几层申请多长的数组this.head.next = new Node[maxLevel];}public void add(T value) {Node[] previous = findPrevious(value);Node<T> node = new Node<>(value, randomLevel());for (int i = 0; i < previous.length && i < node.level; i++) {node.next[i] = previous[i].next[i];previous[i].next[i] = node;}if (node.level > head.level) {for (int i = node.level - 1; i >= 0 && head.next[i] == null; i--) {head.next[i] = node;}head.level = node.level;}}public void remove(T value) {Node[] previous = findPrevious(value);Node node = previous[0].next[0];if (node.value.compareTo(value) != 0) {return;}for (int i = 0; i < previous.length && i < node.level; i++) {previous[i].next[i] = node.next[i];}}public boolean contains(T value) {Node[] previous = findPrevious(value);Node node = previous[0].next[0];return node.value.compareTo(value) == 0;}private int randomLevel() {int level = 1;while (level < maxLevel && Math.random() < continueIncrementLevelThreshold) {level++;}return level;}private Node[] findPrevious(T value) {Node[] previous = new Node[head.level];Node<T> node = head;for (int i = head.level - 1; i >= 0; i--) {while (node.next[i] != null && node.next[i].value.compareTo(value) < 0) {node = node.next[i];}previous[i] = node;}return previous;}/*** head_next level_next # 注释,实际不会打印标题* 67 67* 67 67* 67 67* 67 67* 19 19 67* 19 19 67* 6 6 19 67* 6 6 19 67 82* 6 6 19 46 67 82*/public void show() {StringBuilder sb = new StringBuilder();for (int i = maxLevel; i > 0; i--) {// 这一层级的头指针指向谁Node levelHead = head.next[i - 1];if (levelHead != null) {sb.append(String.format("%-10s", levelHead.value.toString())).append("\t");} else {sb.append(StringUtils.repeat(" ", 10)).append("\t");}// 然后是每一层按层数是否出现打印value或空白填充Node node = head.next[0];while (node != null) {String s = node.value.toString();if (node.level >= i) {sb.append(s).append("\t");} else {sb.append(StringUtils.repeat(" ", s.length())).append("\t");}node = node.next[0];}if (i != 1) {sb.append("\n");}}System.out.println(sb.toString());}private static class Node<T extends Comparable<T>> {// 当前节点的值T value;// 当前节点的层数int level;// 记录当前节点在每一层的next节点Node<T>[] next;private Node(T value, int level) {this.value = value;this.level = level;this.next = new Node[level];}}}
SkipListTest.java:
package alg.link;import java.util.ArrayList;
import java.util.List;
import java.util.Random;/*** @author CC11001100*/
public class SkipListTest {public static void main(String[] args) {SkipList<Integer> skipList = new SkipList<>();Random random = new Random();List<Integer> numList = new ArrayList<>();for (int i = 0; i < 30; i++) {int n = random.nextInt(100);System.out.println("now insert " + n);skipList.add(n);skipList.show();numList.add(n);System.out.println("---------------------------------------------------------------------------");if (Math.random() < 0.5 && !numList.isEmpty()) {int removeNum = numList.remove(random.nextInt(numList.size()));System.out.println("now remove " + removeNum);skipList.remove(removeNum);skipList.show();System.out.println("---------------------------------------------------------------------------");}}}}
测试效果:
now insert 3535 35
35 35
35 35
---------------------------------------------------------------------------
now insert 56
56 56
56 56
56 56
56 56
56 56
56 56
56 56
35 35 56
35 35 56
35 35 56
---------------------------------------------------------------------------
now remove 35
56 56
56 56
56 56
56 56
56 56
56 56
56 56
56 56
56 56
56 56
---------------------------------------------------------------------------
now insert 45
56 56
56 56
56 56
56 56
56 56
45 45 56
45 45 56
45 45 56
45 45 56
45 45 56
---------------------------------------------------------------------------
now remove 5645 45
45 45
45 45
45 45
45 45
---------------------------------------------------------------------------
now insert 745 45
45 45
45 45
45 45
7 7 45
---------------------------------------------------------------------------
now insert 5745 45
45 45
45 45
45 45 57
7 7 45 57
---------------------------------------------------------------------------
now remove 745 45
45 45
45 45
45 45 57
45 45 57
---------------------------------------------------------------------------
now insert 7545 45
45 45
45 45
45 45 57
45 45 57 75
---------------------------------------------------------------------------
now remove 7545 45
45 45
45 45
45 45 57
45 45 57
---------------------------------------------------------------------------
now insert 9645 45
45 45 96
45 45 96
45 45 57 96
45 45 57 96
---------------------------------------------------------------------------
now remove 9645 45
45 45
45 45
45 45 57
45 45 57
---------------------------------------------------------------------------
now insert 40
40 40
40 40
40 40
40 40
40 40
40 40 45
40 40 45
40 40 45
40 40 45 57
40 40 45 57
---------------------------------------------------------------------------
now remove 4045 45
45 45
45 45
45 45 57
45 45 57
---------------------------------------------------------------------------
now insert 6945 45
45 45
45 45 69
45 45 57 69
45 45 57 69
---------------------------------------------------------------------------
now insert 1145 45
11 11 45
11 11 45 69
11 11 45 57 69
11 11 45 57 69
---------------------------------------------------------------------------
now insert 1945 45
11 11 45
11 11 45 69
11 11 19 45 57 69
11 11 19 45 57 69
---------------------------------------------------------------------------
now insert 5545 45
11 11 45
11 11 45 55 69
11 11 19 45 55 57 69
11 11 19 45 55 57 69
---------------------------------------------------------------------------
now remove 5545 45
11 11 45
11 11 45 69
11 11 19 45 57 69
11 11 19 45 57 69
---------------------------------------------------------------------------
now insert 4345 45
11 11 45
11 11 45 69
11 11 19 45 57 69
11 11 19 43 45 57 69
---------------------------------------------------------------------------
now remove 4345 45
11 11 45
11 11 45 69
11 11 19 45 57 69
11 11 19 45 57 69
---------------------------------------------------------------------------
now insert 545 45
11 11 45
11 11 45 69
11 11 19 45 57 69
5 5 11 19 45 57 69
---------------------------------------------------------------------------
now remove 545 45
11 11 45
11 11 45 69
11 11 19 45 57 69
11 11 19 45 57 69
---------------------------------------------------------------------------
now insert 9245 45
11 11 45
11 11 45 69
11 11 19 45 57 69 92
11 11 19 45 57 69 92
---------------------------------------------------------------------------
now remove 4511 11
11 11 69
11 11 19 57 69 92
11 11 19 57 69 92
---------------------------------------------------------------------------
now insert 5611 11
11 11 69
11 11 19 57 69 92
11 11 19 56 57 69 92
---------------------------------------------------------------------------
now insert 3111 11
11 11 69
11 11 19 31 57 69 92
11 11 19 31 56 57 69 92
---------------------------------------------------------------------------
now insert 2911 11
11 11 29 69
11 11 19 29 31 57 69 92
11 11 19 29 31 56 57 69 92
---------------------------------------------------------------------------
now insert 9611 11 96
11 11 29 69 96
11 11 19 29 31 57 69 92 96
11 11 19 29 31 56 57 69 92 96
---------------------------------------------------------------------------
now insert 011 11 96
0 0 11 29 69 96
0 0 11 19 29 31 57 69 92 96
0 0 11 19 29 31 56 57 69 92 96
---------------------------------------------------------------------------
now remove 1911 11 96
0 0 11 29 69 96
0 0 11 29 31 57 69 92 96
0 0 11 29 31 56 57 69 92 96
---------------------------------------------------------------------------
now insert 5411 11 54 96
0 0 11 29 54 69 96
0 0 11 29 31 54 57 69 92 96
0 0 11 29 31 54 56 57 69 92 96
---------------------------------------------------------------------------
now insert 811 11 54 96
0 0 11 29 54 69 96
0 0 11 29 31 54 57 69 92 96
0 0 8 11 29 31 54 56 57 69 92 96
---------------------------------------------------------------------------
now remove 5611 11 54 96
0 0 11 29 54 69 96
0 0 11 29 31 54 57 69 92 96
0 0 8 11 29 31 54 57 69 92 96
---------------------------------------------------------------------------
now insert 6011 11 54 96
0 0 11 29 54 69 96
0 0 11 29 31 54 57 69 92 96
0 0 8 11 29 31 54 57 60 69 92 96
---------------------------------------------------------------------------
now insert 4141 41
11 11 41 54 96
0 0 11 29 41 54 69 96
0 0 11 29 31 41 54 57 69 92 96
0 0 8 11 29 31 41 54 57 60 69 92 96
---------------------------------------------------------------------------
now remove 9241 41
11 11 41 54 96
0 0 11 29 41 54 69 96
0 0 11 29 31 41 54 57 69 96
0 0 8 11 29 31 41 54 57 60 69 96
---------------------------------------------------------------------------
now insert 2041 41
11 11 20 41 54 96
0 0 11 20 29 41 54 69 96
0 0 11 20 29 31 41 54 57 69 96
0 0 8 11 20 29 31 41 54 57 60 69 96
---------------------------------------------------------------------------
now remove 4111 11 20 54 96
0 0 11 20 29 54 69 96
0 0 11 20 29 31 54 57 69 96
0 0 8 11 20 29 31 54 57 60 69 96
---------------------------------------------------------------------------
now insert 5811 11 20 54 96
0 0 11 20 29 54 58 69 96
0 0 11 20 29 31 54 57 58 69 96
0 0 8 11 20 29 31 54 57 58 60 69 96
---------------------------------------------------------------------------
now remove 3111 11 20 54 96
0 0 11 20 29 54 58 69 96
0 0 11 20 29 54 57 58 69 96
0 0 8 11 20 29 54 57 58 60 69 96
---------------------------------------------------------------------------
now insert 7911 11 20 54 96
0 0 11 20 29 54 58 69 96
0 0 11 20 29 54 57 58 69 79 96
0 0 8 11 20 29 54 57 58 60 69 79 96
---------------------------------------------------------------------------
now insert 3811 11 20 54 96
0 0 11 20 29 54 58 69 96
0 0 11 20 29 38 54 57 58 69 79 96
0 0 8 11 20 29 38 54 57 58 60 69 79 96
---------------------------------------------------------------------------
now insert 3111 11 20 54 96
0 0 11 20 29 54 58 69 96
0 0 11 20 29 31 38 54 57 58 69 79 96
0 0 8 11 20 29 31 38 54 57 58 60 69 79 96
---------------------------------------------------------------------------
now remove 7911 11 20 54 96
0 0 11 20 29 54 58 69 96
0 0 11 20 29 31 38 54 57 58 69 96
0 0 8 11 20 29 31 38 54 57 58 60 69 96
---------------------------------------------------------------------------
now insert 7811 11 20 54 78 96
0 0 11 20 29 54 58 69 78 96
0 0 11 20 29 31 38 54 57 58 69 78 96
0 0 8 11 20 29 31 38 54 57 58 60 69 78 96
---------------------------------------------------------------------------
now remove 011 11 20 54 78 96
11 11 20 29 54 58 69 78 96
11 11 20 29 31 38 54 57 58 69 78 96
8 8 11 20 29 31 38 54 57 58 60 69 78 96
---------------------------------------------------------------------------
.
转载于:https://www.cnblogs.com/cc11001100/p/9801252.html
数据结构笔记之跳表(SkipList)相关推荐
- java数据结构红黑树上旋下旋_存储系统的基本数据结构之一: 跳表 (SkipList)
在接下来的系列文章中,我们将介绍一系列应用于存储以及IO子系统的数据结构.这些数据结构相互关联又有着巨大的区别,希望我们能够不辱使命的将他们分门别类的介绍清楚.本文为第一节,介绍一个简单而又有用的数据 ...
- 每日一博 - 如何理解跳表(SkipList)
文章目录 什么是跳跃表SkipList 跳表关键字 Why Skip List Code 跳表-查询 跳表-删除 跳表-插入 小结 完整Code 什么是跳跃表SkipList 跳跃表(简称跳表)由美国 ...
- 跳表-skiplist的简单实现
文章目录 1.什么是跳表-skiplist 2.skiplist的效率如何保证? 3.skiplist的实现 4.skiplist跟平衡搜索树和哈希表的对比 1.什么是跳表-skiplist skip ...
- 为啥 redis 使用 跳表 (skiplist) 而不是使用 red-black?
基本结论 1.实现简单. 2.区间查找快.跳表可以做到O(logn) 的时间复杂度定位区间的起点,然后在原始链表中顺序往后遍历就可以了. 3.并发环境优势.红黑树在插入和删除的时候可能需要做一些reb ...
- 什么是跳表 skiplist ?
什么是跳表 skiplist ? 文章目录 什么是跳表 skiplist ? 特性 实现 结构 查找 插入 删除 完整代码 参考 跳表可以快速地查找.插入.删除.据说可以替代红黑树.Redis中的有序 ...
- 一种数据结构 跳表skiplist
跳表是平衡树的一种替代的数据结构,但是和红黑树不相同的是,跳表对于树的平衡的实现是基于一种随机化的算法的,这样也就是说跳表的插入和删除的工作是比较简单的. 下载地址 : http://download ...
- Redis数据结构之——跳表skiplist
写在前面 以下内容是基于Redis 6.2.6 版本整理总结 一.跳表(skiplist) 如何理解跳表?在了解跳表之前,我们先从普通链表开始,一点点揭开跳表的神秘面纱~ 首先,普通单链表来说,即使链 ...
- 数据结构--跳表SkipList
对单链表查找一个元素的时间复杂度是 O(n) 通过对链表建立多级索引的结构,就是跳表,查找任意数据.插入数据.删除数据的时间复杂度均为 O(log n) 前提:建立了索引,用空间换时间的思路 (每两个 ...
- 数据结构之跳表Skiplist
一.问题引入 二.何为跳表 跳表具有如下性质: 1. 跳表由很多层结构组成: 2.跳表中每一层都是一个有序链表: 3.跳表的最底层(Level 1)的链表包含所有元素: 4.如果一个元素出现在跳表 L ...
最新文章
- 中欧谋定原产地保护-农业大健康·万祥军:战略格局地理标志
- Mysql日志-RedoLog、UndoLog和BinLog的关系捋顺
- codeforces 935E Fafa and Ancient Mathematics 语法树、动态规划
- 使用iBatis数据映射框架吧
- 15款非常有用的前端开发CSS网格(grid system)生成器
- 小D课堂 - 新版本微服务springcloud+Docker教程_5-02 Netflix开源组件断路器
- 版本设置X:none node Title golang版本错误
- linux中dpkg找不到命令_Linux中tree命令的使用
- 基于php的学校固定资产管理系统
- Java中什么是句柄
- windows系统下,在iis管理器(无W3SVC/WAS服务)或网站IIS功能不全(无默认文档、模块、各种规则设置等)
- Java冒泡排序法 经典例题
- Django 2.1文档
- 天狗农业技术网采用的跨平台的Amaze UI设计
- 【coq】函数语言设计 笔记 03 - list
- 有个程序媛上司是什么体验
- 关于AWS亚马逊云计算平台EC2如何删除快照
- freesurfer recon-all并行运算parallel
- 好看的充电宝有哪些?好看的充电宝推荐
- 安卓模拟器刷小米系统_小米安卓模拟器|小米手游模拟器下载 v1.0.0.8 电脑版_小皮网...