package com.company.SkipList;
import java.util.Comparator;
@SuppressWarnings("all")
public class SkipList<K, V> {
private int size;
private static final int MAX_lEVEL = 32; // 节点的next节点的最高层数
private static final double P = 0.25;
private int level; // 实际的有效层数
// 虚拟头结点 不存放任何的东西
private Node<K, V> first;
private Comparator<K> comparator;
public SkipList(Comparator<K> comparator1) {
first = new Node<K, V>(null, null, MAX_lEVEL);
this.comparator = comparator1;
}
private int compare(K key1, K key2) {
return comparator != null ? comparator.compare(key1, key2) : ((Comparable<K>) key1).compareTo(key2);
}
/**
* @param key
* @param value
* @return
* @throws IllegalAccessException 往跳表中加入键值对 prevs中存放前驱节点
*/
public V put(K key, V value) throws IllegalAccessException {
keyCheck(key);
Node<K, V> node = first;
Node<K, V>[] prevs = new Node[level];
for (int i = level - 1; i >= 0; i--) {
int cmp = -1;
while (node.nexts[i] != null && (cmp = compare(key, node.nexts[i].key)) > 0) {
node = node.nexts[i];
}
if (cmp == 0) {
V oldValue = node.nexts[i].value;
node.nexts[i].value = value;
return oldValue;
}
prevs[i] = node;
}
// 添加新的结点
int newlevel = randomLevel(); // 新层数
Node<K, V> newNode = new Node<K, V>(key, value, newlevel);
for (int i = 0; i < newlevel; i++) {
if (i >= level) {
first.nexts[i] = newNode;
} else {
newNode.nexts[i] = prevs[i].nexts[i]; // 新节点的next节点指向它的前驱节点以前指的方向
prevs[i].nexts[i] = newNode; // 前驱节点的后继节点变为新节点
}
}
size++;
level = Math.max(newlevel, level);
return value;
}
// 新节点的Nexts层数
private int randomLevel() {
int level = 1;
while (Math.random() < P && level < MAX_lEVEL) {
level++;
}
return level;
}
/**
* @param key
* @return 查找key对应的value
* @throws IllegalAccessException 从最顶层的nexts数组开始,如果key比对应的key值大,则一直沿着这层向下搜索
* 如果key比对应的key值大,则进入下一层搜索 如果一样大了 就返回value值
*/
public V get(K key) throws IllegalAccessException {
keyCheck(key);
Node<K, V> node = first;
for (int i = level - 1; i >= 0; i--) {
int cmp = -1;
while (node.nexts[i] != null && (cmp = compare(key, node.nexts[i].key)) > 0) {
node = node.nexts[i];
}
if (cmp == 0)
return node.nexts[i].value;
}
return null;
}
/**
* @param key
* @return
* @throws IllegalAccessException 删除目标节点
*/
public V remove(K key) throws IllegalAccessException {
keyCheck(key);
Node<K, V> node = first;
Node<K, V>[] prevs = new Node[level];
boolean exist = false;
for (int i = level - 1; i >= 0; i--) {
int cmp = -1;
while (node.nexts[i] != null && (cmp = compare(key, node.nexts[i].key)) > 0) {
node = node.nexts[i];
}
if (cmp == 0) {
exist = true;
}
prevs[i] = node;
}
// 添加新的结点
if (!exist)
return null;
Node<K, V> removedNode = node.nexts[0];
size--;
for (int i = 0; i < removedNode.nexts.length; i++) {
prevs[i].nexts[i] = removedNode.nexts[i];
}
// 更新跳表的层数
int newLevel = level;
while (--newLevel >= 0 && first.nexts[newLevel] == null) {
level = newLevel;
}
return removedNode.value;
}
public boolean isEmpty() {
return this.size == 0;
}
public int size() {
return this.size;
}
private void keyCheck(K key) throws IllegalAccessException {
if (key == null) {
throw new IllegalAccessException("Key must not be empty!");
}
}
private static class Node<K, V> {
K key;
V value;
Node<K, V>[] nexts;
public Node(K key, V value, int level) {
this.key = key;
this.value = value;
this.nexts = new Node[level];
}
@Override
public String toString() {
return key + ":" + value + "_" + nexts.length;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("一共" + level + "层").append("\n");
for (int i = level - 1; i >= 0; i--) {
Node<K, V> node = first;
while (node.nexts[i] != null) {
sb.append(node.nexts[i]);
sb.append(" ");
node = node.nexts[i];
}
sb.append("\n");
}
return sb.toString();
}
}
Java实现数据结构跳表
最新推荐文章于 2022-02-21 11:36:27 发布
该博客介绍了使用Java实现的跳表数据结构,包括构造虚拟头结点、设置最大层数、随机确定新节点层数、插入、查找和删除等操作。跳表是一种高效的查找数据结构,通过多级索引提高查找效率,适用于快速查找和修改键值对。
摘要由CSDN通过智能技术生成