跳表能够看作是一个带有索引的链表,在介绍跳表以前先看一下一个普通的链表,假如当前维护了一个有序的链表:html
如今要在这个链表中查找128,由于事先不知道链表中数值的分布状况,咱们只能从前到后依次遍历,那么有没有什么取巧的方法呢?java
若是咱们可以存储下最中间节点的引用,好比存储节点29的引用,而后每次要查找节点的时候就先跟29比较一下,若是比29小就仍是从前日后找(由于不会超过中间节点,从前日后和从中间往前区别不大),若是比29大就直接跳到29开始日后找,这种思想就是为链表添加了一个简单的索引,一下能够节省掉一半的查找时间。跳表的设计思想相似,经过为链表的每一个节点设置高度来添加索引,不一样的高度称为不一样的层,每一层的next只能指向当前层的下一个节点,下面是一个跳表的示例:node
最左面一列null为head节点,用于保存每一层的第一个节点,在查找的时候先从最高层开始查找,好比要在上面的跳表中查找128:apache
首先取最高层第六层的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就将层数加一层继续随机,可是随机这种东西毕竟是不可控的,为了不出现太高的层数最好仍是设置一个最大层数以避免某些节点的层数过大。app
跳表的简单Java实现:dom
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:ui
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("---------------------------------------------------------------------------"); } } } }
测试效果:this
now insert 35 35 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 56 45 45 45 45 45 45 45 45 45 45 --------------------------------------------------------------------------- now insert 7 45 45 45 45 45 45 45 45 7 7 45 --------------------------------------------------------------------------- now insert 57 45 45 45 45 45 45 45 45 57 7 7 45 57 --------------------------------------------------------------------------- now remove 7 45 45 45 45 45 45 45 45 57 45 45 57 --------------------------------------------------------------------------- now insert 75 45 45 45 45 45 45 45 45 57 45 45 57 75 --------------------------------------------------------------------------- now remove 75 45 45 45 45 45 45 45 45 57 45 45 57 --------------------------------------------------------------------------- now insert 96 45 45 45 45 96 45 45 96 45 45 57 96 45 45 57 96 --------------------------------------------------------------------------- now remove 96 45 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 40 45 45 45 45 45 45 45 45 57 45 45 57 --------------------------------------------------------------------------- now insert 69 45 45 45 45 45 45 69 45 45 57 69 45 45 57 69 --------------------------------------------------------------------------- now insert 11 45 45 11 11 45 11 11 45 69 11 11 45 57 69 11 11 45 57 69 --------------------------------------------------------------------------- now insert 19 45 45 11 11 45 11 11 45 69 11 11 19 45 57 69 11 11 19 45 57 69 --------------------------------------------------------------------------- now insert 55 45 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 55 45 45 11 11 45 11 11 45 69 11 11 19 45 57 69 11 11 19 45 57 69 --------------------------------------------------------------------------- now insert 43 45 45 11 11 45 11 11 45 69 11 11 19 45 57 69 11 11 19 43 45 57 69 --------------------------------------------------------------------------- now remove 43 45 45 11 11 45 11 11 45 69 11 11 19 45 57 69 11 11 19 45 57 69 --------------------------------------------------------------------------- now insert 5 45 45 11 11 45 11 11 45 69 11 11 19 45 57 69 5 5 11 19 45 57 69 --------------------------------------------------------------------------- now remove 5 45 45 11 11 45 11 11 45 69 11 11 19 45 57 69 11 11 19 45 57 69 --------------------------------------------------------------------------- now insert 92 45 45 11 11 45 11 11 45 69 11 11 19 45 57 69 92 11 11 19 45 57 69 92 --------------------------------------------------------------------------- now remove 45 11 11 11 11 69 11 11 19 57 69 92 11 11 19 57 69 92 --------------------------------------------------------------------------- now insert 56 11 11 11 11 69 11 11 19 57 69 92 11 11 19 56 57 69 92 --------------------------------------------------------------------------- now insert 31 11 11 11 11 69 11 11 19 31 57 69 92 11 11 19 31 56 57 69 92 --------------------------------------------------------------------------- now insert 29 11 11 11 11 29 69 11 11 19 29 31 57 69 92 11 11 19 29 31 56 57 69 92 --------------------------------------------------------------------------- now insert 96 11 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 0 11 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 19 11 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 54 11 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 8 11 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 56 11 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 60 11 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 41 41 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 92 41 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 20 41 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 41 11 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 58 11 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 31 11 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 79 11 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 38 11 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 31 11 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 79 11 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 78 11 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 0 11 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 ---------------------------------------------------------------------------
.