跳表的相关原理参见
redis跳跃表图解&插入详述
import java.util.Random;
/**
* @creat 2021-09-18-2021/9/18
*
* 定义跳表相关信息
*/
public class SkipList<T extends Comparable>{
/**
* 跳表的节点定义
* SkipListLevel类中存储每个层次上的信息
*/
static class SkipListNode<T> {
//后置节点;
public SkipListNode backward;
//结点中保存的值;
T val;
//层次信息;
SkipListLevel[] levels;
public SkipListNode(T val, int l) {
this.val = val;
levels = new SkipListLevel[l];
}
public SkipListNode(int l ) {
levels = new SkipListLevel[l];
}
public SkipListNode() {
}
static class SkipListLevel {
//当前层次的前置节点;
SkipListNode forward;
//距离下个节点的距离;
int span;
}
}
//跳表最大层数
private static final int MAX_LEVEL = 32;
private static final double P = 0.5;
//头节点和尾节点;
private final SkipListNode<T> head;
private final SkipListNode<T> tail;
//当前表的长度
public int length;
//当前表的层
public int level;
public SkipList(){
head = creatNode(MAX_LEVEL);
tail = creatNode();
tail.backward = head;
for(int i = 0; i < MAX_LEVEL; ++i){
head.levels[i] = new SkipListNode.SkipListLevel();
head.levels[i].forward = tail;
head.levels[i].span = 1;
}
tail.backward = head;
level = 1;
}
public void add(T t){
//指向当前访问的结点;
SkipListNode p = this.head;
//从上至下,每一层需要更新的结点;
SkipListNode[] update = new SkipListNode[MAX_LEVEL];
//从上至下,每一层经历过的距离;
int[] distance = new int[MAX_LEVEL + 1];
//遍历到该值合适的插入位置
for(int i = level - 1; i >= 0; --i){
distance[i] = distance[i+1];
while(p.levels[i].forward!=tail && t.compareTo(p.levels[i].forward.val) >= 0 ){
p = p.levels[i].forward;
distance[i] += p.levels[i].span;
}
update[i] = p;
}
//将结点随机分配层级;
int l = RandomLevel();
//创建结点;
SkipListNode<T> node = creatNode(t, l);
//插入Node;
p.levels[0].forward.backward = node;
node.backward = p;
if(l > level){
//如果分配的l > 当前最高层数,将update,distance信息补上
for(int i = level; i < l ; ++i){
update[i] = head;
}
level = l; //将level设置为l;
}
for(int i = 0; i < l; ++i){
//修改每一层插入位置的前一个, 和插入结点的forward
node.levels[i] = new SkipListNode.SkipListLevel();
node.levels[i].forward = update[i].levels[i].forward;
update[i].levels[i].forward = node;
//修改每一层插入位置的前一个, 和插入结点的span
node.levels[i].span = update[i].levels[i].span - (distance[0] - distance[i]);
update[i].levels[i].span = distance[0] + 1 - distance[i];
}
//在 l < level时,更新未涉及到的层次的span
for(int i = l; i < level; ++i){
++update[i].levels[i].span;
}
++this.length;
}
/**
* 为每个待插入的结点随机分配层数
* 设第n层插入概率为Xn
* 则第n+1 层的概率为 p*Xn
* 在本文中设置为 P = 0.5 (注:redis 中设为 0.25)
* @return int
*/
private int RandomLevel() {
Random rand = new Random();
int l = 1;
while(rand.nextInt(Integer.MAX_VALUE) < P * Integer.MAX_VALUE){
l++;
}
return Math.min(l, MAX_LEVEL);
}
public boolean search(T t){
SkipListNode p = head;
for(int i = level - 1; i >= 0; --i){
while(p.levels[i].forward!=tail && t.compareTo(p.levels[i].forward.val) > 0){
p = p.levels[i].forward;
}
}
return p.levels[0].forward == tail ? false :p.levels[0].forward.val.equals(t);
}
/**
* 总体逻辑和插入差不多
* @param t 待删除的元素的值
* @return Boolean 是否有该元素
*/
public boolean delete(T t){
SkipListNode p = head;
SkipListNode[] update = new SkipListNode[level];
for(int i = level - 1; i >= 0; --i){
while(p.levels[i].forward!=tail && t.compareTo(p.levels[i].forward.val) > 0){
p = p.levels[i].forward;
}
update[i] = p;
}
if(p.levels[0].forward==tail || !t.equals(p.levels[0].forward.val)) return false; //没有该元素;
//开始删除
SkipListNode node = p.levels[0].forward; //待删除的结点;
node.levels[0].forward.backward = p;
node.backward = null;
int l = node.levels.length;//该结点的层次;
for(int i = 0; i < l; ++i){
//每一层连接解开;
update[i].levels[i].forward = node.levels[i].forward;
node.levels[i].forward = null;
//更新span信息;
update[i].levels[i].span = update[i].levels[i].span + node.levels[i].span - 1;
}
for(int i = l ; i < level; ++i) --update[i].levels[i].span;
--this.length;
//更新level信息。
for(;level > 1 && head.levels[level-1].forward==tail; --level){}
return true;
}
public T getMax(){
return (T) tail.backward.val;
}
private SkipListNode<T> creatNode() {
return new SkipListNode<>();
}
private SkipListNode<T> creatNode(int len) {
return new SkipListNode<>(len);
}
private SkipListNode<T> creatNode(T t, int l) {
return new SkipListNode<>(t, l);
}
}