跳表(skipList)的原理和java实现
写这个博客的原因是因为看其他人写的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();
}
}

浙公网安备 33010602011771号