跳錶能夠看作是一個帶有索引的鏈表,在介紹跳錶以前先看一下一個普通的鏈表,假如當前維護了一個有序的鏈表: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 ---------------------------------------------------------------------------
.