1 定义
空间复杂度为O(n)。
2 添加
抛硬币法。
时间复杂度为O(logn)。
3 删除
时间复杂度为O(logn)。
4 实现
/**
* 跳表
*
* @author wgm
* @since 2021/4/26
*/
public class SkipList {
private static final Double RATE = 0.5;
private Node head, tail;
private int level;
public SkipList() {
head = new Node(Integer.MIN_VALUE);
tail = new Node(Integer.MAX_VALUE);
head.right = tail;
tail.left = head;
level = 1;
}
public static void main(String[] args) {
SkipList list = new SkipList();
list.insert(50);
list.insert(15);
list.insert(13);
list.insert(20);
list.insert(100);
list.insert(75);
list.insert(99);
list.insert(76);
list.insert(83);
list.insert(65);
list.print();
System.out.println("节点是否存在:" + list.getNode(50));
list.delete(50);
list.print();
System.out.println("节点是否存在:" + list.getNode(50));
}
public void delete(int data) {
Node node = getNode(data);
if (node == null) {
return;
}
remove(node);
node = node.up;
while (node != null) {
if (node.left.data == Integer.MIN_VALUE && node.right.data == Integer.MAX_VALUE) {
removeLevel(node.left, node.right);
} else {
remove(node);
}
node = node.up;
}
}
private void removeLevel(Node removeHead, Node removeTail) {
if (removeHead.up == null && removeTail.up == null) {
removeHead.down.up = null;
removeTail.down.up = null;
head = removeHead.down;
tail = removeTail.down;
} else {
removeHead.up.down = removeHead.down;
removeHead.down.up = removeHead.up;
removeTail.up.down = removeTail.down;
removeTail.down.up = removeTail.up;
}
level--;
}
private void remove(Node node) {
node.left.right = node.right;
node.right.left = node.left;
node.left = null;
node.right = null;
}
public void insert(int data) {
Node preNode = getPreNode(data);
if (preNode.data == data) {
return;
}
Node node = insert(preNode, data);
for (double random = Math.random(); random <= RATE; random = Math.random()) {
Node left = node.left;
Node leftUp;
while (left != null && left.up == null) {
left = left.left;
}
if (left == null) {
insertLevel();
leftUp = head;
} else {
leftUp = left.up;
}
Node up = insert(leftUp, data);
up.down = node;
node.up = up;
node = up;
}
}
private Node insert(Node preNode, int data) {
Node node = new Node(data);
node.right = preNode.right;
node.left = preNode;
preNode.right = node;
node.right.left = node;
return node;
}
private void insertLevel() {
Node newHead = new Node(Integer.MIN_VALUE);
Node newTail = new Node(Integer.MAX_VALUE);
newHead.right = newTail;
newTail.left = newHead;
newHead.down = head;
head.up = newHead;
newTail.down = tail;
tail.up = newTail;
head = newHead;
tail = newTail;
level++;
}
public Node getNode(int data) {
Node preNode = getPreNode(data);
if (preNode.data == data) {
return preNode;
} else {
return null;
}
}
private Node getPreNode(int data) {
Node visitNode = head;
int visitLevel = level;
while (visitLevel >= 1) {
while (visitNode.right != tail && visitNode.right.data <= data) {
visitNode = visitNode.right;
}
if (visitLevel > 1) {
visitNode = visitNode.down;
visitLevel--;
} else {
break;
}
}
return visitNode;
}
public void print() {
Node printHead = this.head;
Node printTail = this.tail;
while (printHead != null) {
Node printNode = printHead;
while (printNode.right != printTail) {
printNode = printNode.right;
System.out.print(printNode + " ");
}
System.out.println();
printHead = printHead.down;
printTail = printTail.down;
}
}
/**
* 节点
*/
private class Node {
private int data;
private Node left, right, up, down;
public Node(int data) {
this.data = data;
}
@Override
public String toString() {
return String.valueOf(data);
}
}
}
5 测试
D:\program\Java\jdk1.8.0_241\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:60934,suspend=y,server=n "-javaagent:C:\Users\GMWANG~1\AppData\Local\Temp\captureAgent948jars\debugger-agent.jar" -Dfile.encoding=UTF-8 -classpath "D:\program\Java\jdk1.8.0_241\jre\lib\charsets.jar;D:\program\Java\jdk1.8.0_241\jre\lib\deploy.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\access-bridge-64.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\cldrdata.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\dnsns.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\jaccess.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\jfxrt.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\localedata.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\nashorn.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\sunec.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\sunjce_provider.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\sunmscapi.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\sunpkcs11.jar;D:\program\Java\jdk1.8.0_241\jre\lib\ext\zipfs.jar;D:\program\Java\jdk1.8.0_241\jre\lib\javaws.jar;D:\program\Java\jdk1.8.0_241\jre\lib\jce.jar;D:\program\Java\jdk1.8.0_241\jre\lib\jfr.jar;D:\program\Java\jdk1.8.0_241\jre\lib\jfxswt.jar;D:\program\Java\jdk1.8.0_241\jre\lib\jsse.jar;D:\program\Java\jdk1.8.0_241\jre\lib\management-agent.jar;D:\program\Java\jdk1.8.0_241\jre\lib\plugin.jar;D:\program\Java\jdk1.8.0_241\jre\lib\resources.jar;D:\program\Java\jdk1.8.0_241\jre\lib\rt.jar;D:\project\untitled\out\production\untitled;D:\program\JetBrains\IntelliJ IDEA 2020.1\lib\idea_rt.jar" SkipList
Connected to the target VM, address: '127.0.0.1:60934', transport: 'socket'
50
50
50
50 75
13 50 75 83 100
13 15 20 50 65 75 76 83 99 100
节点是否存在:50
75
13 75 83 100
13 15 20 65 75 76 83 99 100
节点是否存在:null
Disconnected from the target VM, address: '127.0.0.1:60934', transport: 'socket'
Process finished with exit code 0