Skip List
Skip List
1. overview
- Skip List是一种经过优化的链表,通过存储了冗余的节点作为跳板指针,提供了O(logn)的增删改查效率
- 结构与算法过程较红黑树更容易理解,实现也更简单

- 如果某一层拥有某节点,则其下每一层均有该节点,之间存在指针关联,例如3,5
- 链表的层数在插入节点时有机会更新,采用丢硬币方法,如果产生的新层数newLevel比原始层数level大,则加一层并且且在新层及其以下层均插入节点,否则,在newLevel至底层间所有层插入节点
存储结构如图所示,红色线条代表查询路径,在跳板指针的帮助下,直接跳过了大部分节点,很容易的可以写出搜索代码
首先给出基础的节点定义与变量:
|
|
2. 查找
|
|

3. 插入
- 如图红色区域所示,插入节点的核心思想,找到需要插入层的新节点位置之前的指针,循环指针完成指针指向即可
- 插入节点之前需要确认新的随机层数,之后找到开始插入的层,由上到下
- 注意不要使用每一层都重新查找的方式进行节点插入,可行,但是速度极慢123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475/*** 插入** @param value** @return*/public Node insert(int key, V value) {List<Node> noteToUpdate = Lists.newArrayList();//迭代各层寻找需要插入key节点的前置节点,放入ListNode p = top;while (true) {while (p.next != null && p.next.key <= key) {p = p.next;}noteToUpdate.add(p);if (p.down != null) {p = p.down;} else {break;}}//查询是否存在,如果存在,最后一个节点一定是Node lastOne = noteToUpdate.get(noteToUpdate.size() - 1);if (lastOne.key == key) {return lastOne;}//新层数,如果比现在大,就赋值1,增加一层,否则根据随机值向下寻找插入节点的首层int newLevel = newLevel() - level;newLevel = newLevel > 0 ? 1 : newLevel;Node headNode = top;//新层数小于当前层,则从高层开始,每层插入节点即可while (newLevel != 0) {if (newLevel > 0) {Node oldHead = headNode;headNode = new Node(HEAD_KEY, null, oldHead.level + 1);headNode.down = oldHead;top = headNode;level++;newLevel--;//增加新层,则要插入的节点需要增加,放在List头部,节点就是新headNodenoteToUpdate.add(0, headNode);continue;}if (newLevel < 0) {if (headNode.down != null) {headNode = headNode.down;//插入层向下移动,则要插入的节点需要减少,从头开始减少noteToUpdate.remove(0);}newLevel++;}}//循环各个需要插入的节点进行插入,并配置向下指针//此处从末尾节点开始,方便配置down指针Node bottomNode = null;for (int i = noteToUpdate.size() - 1; i >= 0; i--) {Node pre = noteToUpdate.get(i);Node preNext = pre.next;Node node = new Node(key, value, pre.level);pre.next = node;node.next = preNext;node.down = bottomNode;bottomNode = node;}count++;return null;}
4. 更新
- 如图蓝色路径显示,找到该节点,从上到下更新即可
|
|
5. 删除
- 如图紫色路径显示,找到该节点的所有前驱,从上到下更新指向下一个节点即可
- 同时需要处理空层,将其去除
|
|
6. 打印跳表结构
|
|
7. 测试
- 插入应该仍有优化空间12345678ArrayList插入时间:174ms , 数量:5000000ArrayList搜索时间:18msLinkedList插入时间:2991ms , 数量:5000000LinkedList搜索时间:31msSkipList插入时间:3717ms , 数量:5000000,层数:22SkipList搜索时间:0msRBtree插入时间:1583ms , 数量:5000000RBtree搜索时间:0ms







