Project Introduction
- This project decomposes the common written interview questions of major factories, traces the source to the underlying implementation principles of data structures and algorithms, and knows what they are.
- Establish a knowledge structure system for easy search, welcome more like-minded friends to join the project AlgorithmPractice, (issues and pull requests are welcome).
1. Title description
-
What is a jump table: A jump table is a linked list that can be searched in half. It inserts a mark pointer into the source linked list, and then the mark pointer is also stringed into a linked list, so that the purpose of quickly finding a value is achieved by searching for the mark pointer. Similarly, if the mark pointer is too long, the mark pointer can be marked again, similar to a multi-level cache.
-
Jump table and its implementation : (The methods mainly include: add() , delete() , find() , initial() , print() ).
-
Code implementation : SkipList
Second, problem-solving ideas
First, prepare a data structure of a Node node. We assume that each linked list value of this quick table is sorted from small to large, and all starting values are set to Integer.MIN_VALUE.
class SkipListNode {
int value;
SkipListNode next;
SkipListNode down;
public SkipListNode() {
this.value = Integer.MIN_VALUE;
next = null;
down = null;
}
public SkipListNode(int value) {
this.value = value;
next = null;
down = null;
}
}
1. The initial() method
When each linked list is initialized, two nodes at the beginning and the end are required. Note that the values of the head node and the end node are set to (from small to large):public static final int HEAD_KEY = Integer.MIN_VALUE;
public static final int TAIL_KEY = Integer.MAX_VALUE;
Every time it is initialized, it is necessary to exchange the links between the old and new nodes and the end nodes.
public SkipListNode initial() {
SkipListNode phead = new SkipListNode();
SkipListNode ptail = new SkipListNode();
phead.value = HEAD_KEY;
ptail.value = TAIL_KEY;
phead.next = ptail;
return phead;
}
2. add() method
The add method first determines whether the nodes exist, if they exist, they return directly, if they do not exist, they first determine whether it is necessary to create a new layer of tag pointers based on the source linked list.public void add(int Value) {
if (find(Value)) {
return;
}
SkipListNode insertKey;
SkipListNode fathersln = null;
/* 经过实验证明:查找 耗时 比 插入 更加耗时。
层数越高,整个数据备份越多,越臃肿,但是查找快、插入和删除慢
层数越低,整个数据备份越少, 但是查找慢、插入和删除快
综合考虑,建议层数高
*/
//无需新建层数
if (SkipListnum <= (2 << SkipListlevel - 1)) {
int k = randomLevel();
insertKey = head;
for (int i = 0; i < k; i++) {
insertKey = insertKey.down;
}
} else {
//需要新建层数
SkipListNode phead = initial();
phead.down = head;
phead.next.down = tail;
head = phead;
tail = phead.next;
insertKey = head;
SkipListlevel++;
}
//向下补全所有的插入节点
while (insertKey != null) {
while (insertKey.next.value < Value) {
insertKey = insertKey.next;
}
SkipListNode sln = new SkipListNode(Value);
if (fathersln != null) {
fathersln.down = sln;
}
sln.next = insertKey.next;
insertKey.next = sln;
insertKey = insertKey.down;
fathersln = sln;
}
SkipListnum++;
}
3. The delete() method
The deletion method needs to pay attention to three points: 1. The number of surface layers is downgraded, 2. The value is searched horizontally, and 3. The value is searched vertically.public boolean delete(int x) {
//快表层高降级
if (head.next == tail && head.down != null) {
head = head.down;
tail = tail.down;
this.SkipListlevel--;
}
//注意顺序:先降级、再判断不然会出现最后一个元素删除了,但是表级仍然不为1
if (!find(x)) {
return false;
}
SkipListNode point = head;
SkipListNode prepoint = point;
//横向查找
while (point.value != x) {
while (point.next.value <= x) {
prepoint = point;
point = point.next;
}
if (point.value == x) {
break;
}
point = point.down;
prepoint = prepoint.down;
if (point.equals(prepoint)) {
continue;
}
while (prepoint.next != point) {
prepoint = prepoint.next;
}
}
//纵向删除
while (prepoint != null) {
point = point.down;
prepoint.next = prepoint.next.next;
prepoint = prepoint.down;
//循环至最低点结束
while (prepoint != null && prepoint.next != point) {
prepoint = prepoint.next;
}
}
this.SkipListnum--;
return true;
}
4. find() method
public boolean find(int x) {
SkipListNode point = head;
while (true) {
while (point.next.value <= x) {
point = point.next;
}
if (point.value == x) {
return true;
}
if (point.down == null) {
//到达最底层
return false;
}
point = point.down;
}
}
5. The print() method
The output is the overall structure of the linked list from top to bottom.public void print() {
//输出链表的整体结构
SkipListNode point;
SkipListNode headpoint = head;
while (headpoint != null) {
point = headpoint;
while (point.value != TAIL_KEY) {
if (point.value != HEAD_KEY) {
System.out.print(point.value + "-");
}
point = point.next;
}
System.out.println();
headpoint = headpoint.down;
}
}