/**
* 跳錶節點數據存儲結構
*/
class SkipNode<E extends Comparable<? super E>> {
public final E value; //節點存儲的數據
public final SkipNode<E>[] forward; //節點的指針數組
/**
* 根據節點的層級構造一個節點
* @param level 節點層級
* @param value 節點存儲值
*/
@SuppressWarnings("unchecked")
public SkipNode(int level, E value) {
forward = new SkipNode[level + 1];//level層的元素後面帶着level+1的指針數組
this.value = value;
}
}
public class SkipSet<E extends Comparable<? super E>> {
/**
* 概率因子,實驗證明p=1/e比p=0.5要好,e是個神奇的數字!
*/
// public static final double P = 0.5;
public static final double P = 1/Math.E;
/**
* 最大層級
*/
public static final int MAX_LEVEL = 6;
/**
* 開始節點,不存值,貫穿所有層
*/
public final SkipNode<E> header = new SkipNode<E>(MAX_LEVEL, null);
/**
* 當前跳錶的最高層級
*/
public int level = 0;
/**
* 插入一個元素
* @param value 待插入值
*/
@SuppressWarnings("unchecked")
public void insert(E value) {
SkipNode<E> x = header;
SkipNode<E>[] update = new SkipNode[MAX_LEVEL + 1];
//查找元素的位置,這裏其實做了一次contain操作,註釋見contain
for (int i = level; i >= 0; i--) {
while (x.forward[i] != null
&& x.forward[i].value.compareTo(value) < 0) {
x = x.forward[i];
}
//update[i]是比value小的數裏面最大的,是value的前置節點
update[i] = x;
}
x = x.forward[0];
//此處不允許插入相同元素,爲一個set
if (x == null || !x.value.equals(value)) {//跳錶中不包含所要插的元素
//隨機產生插入的層級
int lvl = randomLevel();
//產生的隨機層級比當前跳錶的最高層級大,需要添加相應的層級,並更新最高層級
if (lvl > level) {
for (int i = level + 1; i <= lvl; i++) {
update[i] = header;
}
level = lvl;
}
//生成新節點
x = new SkipNode<E>(lvl, value);
//調整節點的指針,和指向它的指針
for (int i = 0; i <= lvl; i++) {
x.forward[i] = update[i].forward[i];
update[i].forward[i] = x;
}
}
}
/**
* 刪除一個元素
* @param value 待刪除值
*/
@SuppressWarnings("unchecked")
public void delete(E value) {
SkipNode<E> x = header;
SkipNode<E>[] update = new SkipNode[MAX_LEVEL + 1];
//查找元素的位置,這裏其實做了一次contain操作,註釋見contain
for (int i = level; i >= 0; i--) {
while (x.forward[i] != null
&& x.forward[i].value.compareTo(value) < 0) {
x = x.forward[i];
}
update[i] = x;
}
x = x.forward[0];
//刪除元素,調整指針
if (x.value.equals(value)) {
for (int i = 0; i <= level; i++) {
if (update[i].forward[i] != x)
break;
update[i].forward[i] = x.forward[i];
}
//如果元素爲本層最後一個元素,則刪除同時降低當前層級
while (level > 0 && header.forward[level] == null) {
level--;
}
}
}
/**
* 查找是否包含此元素
* @param searchValue 帶查找值
* @return true:包含;false:不包含
*/
public boolean contains(E searchValue) {
SkipNode<E> x = header;
//從開始節點的最高層級開始查找
for (int i = level; i >= 0; i--) {
//當到達本層級的NULL節點或者遇到比查找值大的節點時,轉到下一層級查找
while (x.forward[i] != null
&& x.forward[i].value.compareTo(searchValue) < 0) {
x = x.forward[i];
}
}
x = x.forward[0];
//此時x有三種可能,1.x=null,2.x.value=searchValue,3.x.value>searchValue
return x != null && x.value.equals(searchValue);
}
/**
* 這裏是跳錶的精髓所在,通過隨機概率來判斷節點的層級
* @return 節點的層級
*/
public static int randomLevel() {
int lvl = (int) (Math.log(1. - Math.random()) / Math.log(1. - P));
return Math.min(lvl, MAX_LEVEL);
}
/**
* 輸出跳錶的所有元素
* 遍歷最底層的元素即可
*/
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{");
SkipNode<E> x = header.forward[0];
while (x != null) {
sb.append(x.value);
x = x.forward[0];
if (x != null)
sb.append(",");
}
sb.append("}");
return sb.toString();
}
}
以上是跳躍表在java裏的實現