有序表所有的操作都是 有序表 - 跳表 - 图1 的。有很多数据结构可以实现有序表,如:红黑树、AVL(Self-Balancing Binary Search Tree)、SBT(Size-Balance-Tree)、跳表(skip-List)等。

AVL,SBT,红黑树都可以参考 各种树

跳表

对于一个跳表来说,依次插入数据:3,20,40,50,10,30,100,15

image.png
插入 3,roll 到层高为 3,找到比 3 小的最右节点为 null,head 的层高为 0, 0<3,将 head 的层高增加到 3 层,并将每层都指向 3 节点
image.png

插入 20,roll 到层高为 5,找到比 20 小的最右节点为 3,head 的层高为 3, 3<5,将 head 的层高增加到 5 层,3 节点所有层指向 20 节点,head 节点的最高两层指向 20 节点

image.png
插入 40,roll 到层高为 4,找到比 40 小的最右节点为 20,head 的层高为 5, 5>4,head 层高不变,20 节点 4 个层指向 40 节点
image.png
插入 50,roll 到层高为 5,找到比 50 小的最右节点为 50,head 的层高为 5, 5==5,head 层高不变,40 节点所有层指向 50 节点,20 节点的最高层指向 50节点
image.png
插入 10,roll 到层高为 2,找到比 10 小的最右节点为 3,head 的层高为 5, 5>2,head 层高不变,3 节点 0、1 层指向 10 节点,10 节点的所有层指向 20节点
image.png
插入 30,roll 到层高为 1,找到比 30 小的最右节点为 20,head 的层高为 5, 5>1,head 层高不变,20 节点 0 层指向 30 节点,30 节点的所有层指向 40 节点
image.png
插入 100,roll 到层高为 6,找到比 100 小的最右节点为 50,head 的层高为 6, 5<6,head 层高增加到 6,50 节点的所层点指向 100 节点,head 节点的 5 层指向 100 节点
image.png
插入 15,roll 到层高为 4,找到比 15 小的最右节点为 10,head 的层高为 6, 6>4,head 层高不变,10 节点所有层指向 15 节点,3 节点的 2 层指向 15 节点, head 的 3 层执行 15 节点
image.png
至此,所有节点插入完成。在这个过程中,最重要的过程有两个:

  1. 如何找到小于插入值的最大值?
  2. 找到该值要插入的地方后如果修改

例如:在插入 10 节点时
image.png

  • 先遍历 head 节点,从最高层遍历:
    • 第 4 层 —> 20,20 > 10
    • 第 3 层 —> 20,20 > 10
    • 第 2 层 —> 3,3 < 10
  • 开始遍历 3 节点:
    • 第 2 层 —> 20,20 > 10
  • 遍历结束,小于 10 的最大值为 3,就将 10 插入到 3 节点后

10 的层高为 2,3 节点的 0、1 两层要指向 10 节点,10 节点指向 20 节点

结果为:
image.png

例如:插入 15 时:
image.png

  • 从 head 节点最高层开始遍历:
    • 第 5 层 —> 100,100 > 15
    • 第 4 层 —> 20,20 > 15
    • 第 3 层 —> 20,20 > 15
    • 第 2 层 —> 3,3 < 15
  • 从 3 节点开始遍历:
    • 第 2 层 —> 20,20 > 15
    • 第 1 层 —> 10,10 < 15
  • 遍历结束,15 要插入到 10 后面

15 的层高为 4,10 节点的0、1要指向 15 节点, 3 节点的 2 层要指向 15 节点,head 的 3 层要指向15 节点;15 节点指向 20 节点

结果为:
image.png

代码实现:

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. public class SkipList {
  4. public static class SkipListNode<K extends Comparable<K>, V> {
  5. public K key;
  6. public V val;
  7. public List<SkipListNode<K, V>> nextNodes;
  8. public SkipListNode(K key, V val) {
  9. this.key = key;
  10. this.val = val;
  11. nextNodes = new ArrayList<>();
  12. }
  13. /**
  14. * {@code otherKey} 是否要比 key 小
  15. *
  16. * @param otherKey
  17. * @return
  18. */
  19. public boolean isKeyLess(K otherKey) {
  20. return otherKey != null && (key == null || key.compareTo(otherKey) < 0);
  21. }
  22. /**
  23. * {@code otherKey} 是否 key 相等
  24. *
  25. * @param otherKey
  26. * @return
  27. */
  28. public boolean isKeyEqual(K otherKey) {
  29. return key == null && otherKey == null ||
  30. key != null && otherKey != null && key.compareTo(otherKey) == 0;
  31. }
  32. }
  33. public static class SkipListMap<K extends Comparable<K>, V> {
  34. private static final double PROBABILITY = 0.5;
  35. private SkipListNode<K, V> head;
  36. private int size;
  37. private int maxLevel;
  38. public SkipListMap() {
  39. head = new SkipListNode<>(null, null);
  40. head.nextNodes.add(null);
  41. size = 0;
  42. maxLevel = 0;
  43. }
  44. /**
  45. * 是否包含 key
  46. *
  47. * @param key
  48. * @return
  49. */
  50. public boolean containsKey(K key) {
  51. if (key == null) return false;
  52. SkipListNode<K, V> less = mostRightLessNodeInTree(key);
  53. SkipListNode<K, V> next = less.nextNodes.get(0);
  54. return next != null && next.isKeyEqual(key);
  55. }
  56. /**
  57. * 新增数据
  58. *
  59. * @param key
  60. * @param value
  61. */
  62. public void put(K key, V value) {
  63. if (key == null) return;
  64. SkipListNode<K, V> less = mostRightLessNodeInTree(key);
  65. SkipListNode<K, V> find = less.nextNodes.get(0);
  66. if (find != null && find.isKeyEqual(key)) {
  67. // 值相同
  68. find.val = value;
  69. } else {
  70. // 值不同
  71. size++;
  72. int newNodeLevel = 0;
  73. // roll 层高
  74. while (Math.random() < PROBABILITY) {
  75. newNodeLevel++;
  76. }
  77. while (newNodeLevel > maxLevel) {
  78. // 新节点的层高 > 最大层高,head 需要增加层高
  79. head.nextNodes.add(null);
  80. maxLevel++;
  81. }
  82. // 新节点
  83. SkipListNode<K, V> newNode = new SkipListNode<>(key, value);
  84. // 初始化层高
  85. for (int i = 0; i <= newNodeLevel; i++) {
  86. newNode.nextNodes.add(null);
  87. }
  88. int level = maxLevel;
  89. SkipListNode<K, V> pre = head;
  90. // 设置前后节点每层的指向
  91. while (level >= 0) {
  92. pre = mostRightLessNodeInLevel(key, pre, level);
  93. if (level <= newNodeLevel) {
  94. newNode.nextNodes.set(level, pre.nextNodes.get(level));
  95. pre.nextNodes.set(level, newNode);
  96. }
  97. level--;
  98. }
  99. }
  100. }
  101. /**
  102. * 获取 key 的节点信息
  103. *
  104. * @param key
  105. * @return
  106. */
  107. public V get(K key) {
  108. if (key == null) return null;
  109. SkipListNode<K, V> less = mostRightLessNodeInTree(key);
  110. SkipListNode<K, V> next = less.nextNodes.get(0);
  111. return next != null && next.isKeyEqual(key) ? next.val : null;
  112. }
  113. /**
  114. * 删除 key
  115. *
  116. * @param key
  117. */
  118. public void remove(K key) {
  119. if (!containsKey(key)) return;
  120. size--;
  121. int level = maxLevel;
  122. SkipListNode<K, V> pre = head;
  123. while (level >= 0) {
  124. pre = mostRightLessNodeInLevel(key, pre, level);
  125. SkipListNode<K, V> next = pre.nextNodes.get(level);
  126. // 清除指向
  127. if (next != null && next.isKeyEqual(key)) {
  128. pre.nextNodes.set(level, next.nextNodes.get(level));
  129. }
  130. // 判断是否影响最大层高
  131. if (level != 0 && pre == head && pre.nextNodes.get(level) == null) {
  132. head.nextNodes.remove(level);
  133. maxLevel--;
  134. }
  135. level--;
  136. }
  137. }
  138. /**
  139. * 第一个(最小)节点的 key
  140. *
  141. * @return
  142. */
  143. public K firstKey() {
  144. return head.nextNodes.get(0) != null ? head.nextNodes.get(0).key : null;
  145. }
  146. /**
  147. * 返回最后一个(最大)节点 key
  148. *
  149. * @return
  150. */
  151. public K lastKey() {
  152. int level = maxLevel;
  153. SkipListNode<K, V> cur = head;
  154. while (level >= 0) {
  155. // 从最高层遍历,中间可以跳过很多的数据
  156. SkipListNode<K, V> next = cur.nextNodes.get(level);
  157. while (next != null) {
  158. cur = next;
  159. next = cur.nextNodes.get(level);
  160. }
  161. level--;
  162. }
  163. return cur.key;
  164. }
  165. /**
  166. * 大于等于 key 的最小值
  167. *
  168. * @param key
  169. * @return
  170. */
  171. public K ceillingKey(K key) {
  172. if (key == null) return null;
  173. SkipListNode<K, V> less = mostRightLessNodeInTree(key);
  174. SkipListNode<K, V> next = less.nextNodes.get(0);
  175. return next != null ? next.key : null;
  176. }
  177. /**
  178. * 小于等于 key 的最大值
  179. *
  180. * @param key
  181. * @return
  182. */
  183. public K floorKey(K key) {
  184. if (key == null) return null;
  185. SkipListNode<K, V> less = mostRightLessNodeInTree(key);
  186. SkipListNode<K, V> next = less.nextNodes.get(0);
  187. return next != null && next.isKeyEqual(key) ? next.key : less.key;
  188. }
  189. public int size() {
  190. return size;
  191. }
  192. /**
  193. * 得到小于 key 的最大(最右侧)的值
  194. *
  195. * @param key
  196. * @return
  197. */
  198. private SkipListNode<K, V> mostRightLessNodeInTree(K key) {
  199. if (key == null) return null;
  200. int level = maxLevel;
  201. SkipListNode<K, V> cur = head;
  202. while (level >= 0) {
  203. cur = mostRightLessNodeInLevel(key, cur, level--);
  204. }
  205. return cur;
  206. }
  207. /**
  208. * 本层小于 {@code key} 最右的节点
  209. *
  210. * @param key
  211. * @param cur
  212. * @param level
  213. * @return
  214. */
  215. private SkipListNode<K, V> mostRightLessNodeInLevel(K key, SkipListNode<K, V> cur, int level) {
  216. SkipListNode<K, V> next = cur.nextNodes.get(level);
  217. while (next != null && next.isKeyLess(key)) {
  218. cur = next;
  219. next = cur.nextNodes.get(level);
  220. }
  221. return cur;
  222. }
  223. }
  224. // for test
  225. public static void printAll(SkipListMap<String, String> obj) {
  226. for (int i = obj.maxLevel; i >= 0; i--) {
  227. System.out.print("Level " + i + " : ");
  228. SkipListNode<String, String> cur = obj.head;
  229. while (cur.nextNodes.get(i) != null) {
  230. SkipListNode<String, String> next = cur.nextNodes.get(i);
  231. System.out.print("(" + next.key + " , " + next.val + ") ");
  232. cur = next;
  233. }
  234. System.out.println();
  235. }
  236. }
  237. public static void main(String[] args) {
  238. SkipListMap<String, String> test = new SkipListMap<>();
  239. printAll(test);
  240. System.out.println("======================");
  241. test.put("A", "10");
  242. printAll(test);
  243. System.out.println("======================");
  244. test.remove("A");
  245. printAll(test);
  246. System.out.println("======================");
  247. test.put("E", "E");
  248. test.put("B", "B");
  249. test.put("A", "A");
  250. test.put("F", "F");
  251. test.put("C", "C");
  252. test.put("D", "D");
  253. printAll(test);
  254. System.out.println("======================");
  255. System.out.println(test.containsKey("B"));
  256. System.out.println(test.containsKey("Z"));
  257. System.out.println(test.firstKey());
  258. System.out.println(test.lastKey());
  259. System.out.println(test.floorKey("D"));
  260. System.out.println(test.ceillingKey("D"));
  261. System.out.println("======================");
  262. test.remove("D");
  263. printAll(test);
  264. System.out.println("======================");
  265. System.out.println(test.floorKey("D"));
  266. System.out.println(test.ceillingKey("D"));
  267. }
  268. }