个人学习跳表网站:https://blog.csdn.net/pcwl1206/article/details/83512600
跳表思想类似于二分查找,只不过用在链表上。但是又不能弄成平衡的二分查找(保持平衡耗费的性能很高),所以加入随机数,随机高度,保证效率不会太低。
跳表的查询复杂度是O(lgn),仅插入或删除的复杂度是O(1),但是插入、删除之前需要先查询位置,所以还是O(lgn)
图不会画,还是看链接的地址吧。
该题java代码:
class Skiplist {
private static final int MAX_LEVEL = 16; // 结点的个数
private int levelCount = 1; // 索引的层级数
private Node head = new Node(); // 头结点
private Random random = new Random();
public Skiplist() {
}
public boolean search(int target) {
Node p = head;
for (int i = levelCount - 1; i >= 0; --i) {
while (p.next[i] != null && p.next[i].data < target) {
p = p.next[i];
}
}
if (p.next[0] != null && p.next[0].data == target) {
return true; // 找到,则返回原始链表中的结点
} else {
return false;
}
}
public void add(int num) {
int level = randomLevel();
Node newNode = new Node();
newNode.data = num;
newNode.maxLevel = level; // 通过随机函数改变索引层的结点布置
Node update[] = new Node[level];
for (int i = 0; i < level; ++i) {
update[i] = head;
}
Node p = head;
for (int i = level - 1; i >= 0; --i) {
while (p.next[i] != null && p.next[i].data < num) {
p = p.next[i];
}
update[i] = p;
}
for (int i = 0; i < level; ++i) {
newNode.next[i] = update[i].next[i];
update[i].next[i] = newNode;
}
if (levelCount < level) {
levelCount = level;
}
}
public boolean erase(int num) {
boolean deleted = false;
Node[] update = new Node[levelCount];
Node p = head;
for (int i = levelCount - 1; i >= 0; --i) {
while (p.next[i] != null && p.next[i].data < num) {
p = p.next[i];
}
update[i] = p;
}
if (p.next[0] != null && p.next[0].data == num) {
for (int i = levelCount - 1; i >= 0; --i) {
if (update[i].next[i] != null && update[i].next[i].data == num) {
update[i].next[i] = update[i].next[i].next[i];
deleted = true;
}
}
}
return deleted;
}
// 随机函数
private int randomLevel() {
int level = 1;
for (int i = 1; i < MAX_LEVEL; ++i) {
if (random.nextInt() % 2 == 1) {
level++;
}
}
return level;
}
// Node内部类
public class Node {
private int data = -1;
private Node next[] = new Node[MAX_LEVEL];
private int maxLevel = 0;
}
}