寫這個博客的原因是因為看其他人寫的java實現的跳表代碼總是有點看不懂,原理倒是比較清楚,所以自己動手寫了一個簡單的跳表,希望能給看這塊兒數據結構的同學一個啟發,原理我覺得這篇文章寫的不錯,推薦給大家:https://blog.csdn.net/pcwl1206/article/details/83512600?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
不多說,直接貼代碼:
package com.example.demo;
import java.util.Random;
/**
* 跳表的實現
*/
public class SkipList {
public static final int MAX_LEVEL = 16; //跳表所允許的最大層級
private SkipListNode head = new SkipListNode(null, MAX_LEVEL);
private Random random = new Random();
private int usedLevel = 1; //當前跳表使用中的最大層級
public void insert(int value) {
int level = randomLevel(); //找出當前插入值隨機最大層數
//遍歷節點並插入
insert(value, level);
}
public void delete(int value) {
//從最高層開始,尋找節點
int level = usedLevel;
while(level >= 1) {
level--;
SkipListNode searchResult = search(value, level);
if(searchResult != null) {
deleteNode(searchResult);
break;
}
}
}
//逐層打印
public void print() {
int level = usedLevel;
while(level >= 1) {
level--;
printLevel(level);
}
}
private void printLevel(int level) {
SkipListNode current = head;
String result = new String();
while (current.next[level] != null) {
result = result + current.next[level].data + " -> ";
current = current.next[level];
}
System.out.println("第 " + level + " 層的數據為 : " + result);
}
private void deleteNode(SkipListNode searchResult) {
//將當前節點的前置節點和后置節點關聯起來即可
int currentLevel = searchResult.getMaxlevel();
while(currentLevel >= 1) {
currentLevel--;
//當前節點的前置節點的后置節點 = 當前節點的后置節點
searchResult.pre[currentLevel].next[currentLevel] = searchResult.next[currentLevel];
if(searchResult.next[currentLevel] != null) {
//如果當前節點的后置節點不為null
//當前節點的額后置節點的前置節點 = 當前節點的前置節點
searchResult.next[currentLevel].pre[currentLevel] = searchResult.pre[currentLevel];
}
}
}
private SkipListNode search(int value, int level) {
//從頭開始遍歷
SkipListNode current = head;
while(current.next[level] != null && current.next[level].data < value) {
current = current.next[level];
}
if(current.next[level] == null || current.next[level].data != value) {
//如果搜索到最后,或者已經搜索到比尋找值大的節點了
return null;
}
return current.next[level];
}
private void insert(int value, int level) {
SkipListNode node = new SkipListNode(value, level); //構造當前節點
int currentLevel = level;
while(currentLevel-- > 0) {
//從最高層開始,遍歷每一層
if(head.next[currentLevel] == null) {
//如果當前沒有插入任何元素,直接插入即可
head.next[currentLevel] = node;
node.pre[currentLevel] = head;
} else {
SkipListNode current = head.next[currentLevel], pre = head;
//從第一個元素開始遍歷
while(current != null && current.data < value) {
pre = current;
current = current.next[currentLevel];
}
//設置前置節點的后置節點為當前節點
pre.next[currentLevel] = node;
node.pre[currentLevel] = pre;
if(current != null) {
//如果沒有遍歷到結尾,則需要設置當前節點的前置節點
current.pre[currentLevel] = node;
node.next[currentLevel] = current;
}
}
}
usedLevel = usedLevel > level ? usedLevel : level;
}
//隨機生成函數,即對於任意一個要插入跳表的節點,它的層級為多少
private int randomLevel() {
int level = 1;
for(int i = 1; i < MAX_LEVEL; i++) {
if(random.nextInt() % 2 == 1) {
level++;
}
}
return level;
}
private class SkipListNode{
private Integer data;
private SkipListNode[] next; //后置節點
private SkipListNode[] pre; //前置節點,方便刪除使用
public SkipListNode(Integer data, int maxLevel) {
this.data = data;
next = new SkipListNode[maxLevel];
pre = new SkipListNode[maxLevel];
}
int getMaxlevel() {
return next.length;
}
}
public static void main(String[] args) {
SkipList skipList = new SkipList();
skipList.insert(10);
skipList.insert(25);
skipList.insert(83);
skipList.insert(20);
skipList.print();
System.out.println("------------------");
skipList.delete(83);
skipList.delete(20);
skipList.print();
}
}
