算法 - SkipList实现
什么是跳表
从数据结构上来说,跳表是一个具有层次结构且有着顺序的链表,通过增加一个高度指针和维护顺序来换取高效的CRUD复杂度为logn,着相当于用空间换取时间结构如下
数据结构
@AllArgsConstructor
private static class Node<T extends Comparable<? super T>> {
private Node right;
private Node down;
private T data;
}

Step 1 : 从最简单的操作入手:判断一个某个数据是否在跳表中
传统的链表需要从头到尾为遍历来判断,而在跳表中依旧如此只是增加了层次间迭代的维度
public <T extends Comparable<? super T>> boolean beExists(T target) {
for (Node scanner = head; Objects.nonNull(scanner); scanner = scanner.down) {
while (Objects.nonNull(scanner.right) && scanner.right.data.compareTo(target) < 0) {
scanner = scanner.right;
}
if (Objects.nonNull(scanner.right) && scanner.right.data.equals(target)) {
return true;
}
}
return false;
}
这种遍历方式也叫right-down迭代
Step 2 : 删除一个元素
也是和传统List类似通过引用覆盖的方式删除
public <T extends Comparable<? super T>> boolean remove(T target) {
Objects.requireNonNull(target, "target cannot be null");
boolean beRemoveSuccess = false;
for (Node scanner = head; Objects.nonNull(scanner); scanner = scanner.down) {
//skip it when low target
while (Objects.nonNull(scanner.right) && scanner.right.data.compareTo(target) < 0) {
scanner = scanner.right;
}
//delete it when only equals
if (Objects.nonNull(scanner.right) && scanner.right.data.compareTo(target) == 0) {
scanner.right = scanner.right.right;
beRemoveSuccess = true;
}
}
return beRemoveSuccess;
}
Step 3 : 新增元素
新增的差异很大,主要需要维护合理的高度
❓ 新增节点时要考虑Skip List的高度怎么维护 ?难点在于高度太高会影响维护的效率,太少有可能被拉成一个普通的排序链表。 在参考Redis源码时,主要使用扔骰子的方式来决定是否继续增加一层高度。
private final Random random = new Random();
private Node[] closestNodes = new Node[32];
private Node head = new Node(null, null, null);
public <T extends Comparable<? super T>> void add(T target) {
int level = -1;
//right-down search
for (Node scanner = head; Objects.nonNull(scanner) ; scanner = scanner.down) {
while (Objects.nonNull(scanner.right) && scanner.right.data.compareTo(target) < 0) {
scanner = scanner.right;
}
//find equals or greater
closestNodes[++level] = scanner;
}
boolean beNeedCreateNextNode = true;
Node createdNode = null, closestNode;
while (beNeedCreateNextNode && level > -1) {
closestNode = closestNodes[level--];
//create node, the key is update down pointer
closestNode.right = (createdNode = new Node(closestNode.right, createdNode, target));
//random decision
beNeedCreateNextNode = random.nextBoolean();
}
if (beNeedCreateNextNode) {
head = new Node(new Node(null, createdNode, target), head, null);
}
}

浙公网安备 33010602011771号