跳表可以认为同样包含key和value,可以完成任何红黑树包含的操作。同时代价也是O(logN)。
但是底层不是数结构,比较魔性,但是也好实现。
跳表思想:
key包含多少层,不是由key本身决定的,而是随机的。随机函数只包含0和1,roll出1时最少层数确定,第几次roll出1,则系统最小有几层。
数据插入:重新roll,得到该key的层数,此时从高层开始计算数据是否应该插入该位置,算得位置后,从上层到下层挨个计算数据插入位置,最后形成一个竖直的node。
总体思想:由于每次key包含几层都是需要roll的,所以第一层的数目最多,第二层数目概率为一半,第三层再一半。。。越向上层数中所包含的点数越少,此时当我们从上层从左往右移动的过程中,会越过非常多低层的点,可以极大的增大效率。数据量足够大时,可以发现此时由于概率层数,整个跳表此时近似可以认为是一棵平衡搜索二叉树。
代码
public static class SkipListNode{
public Integer value;
//此数组为层数,list中存放的内容为每一层中的下一个节点,0层存放的永远都是null,下一个节点又会包含所有的信息,总共有roll出的层加一层。
public ArrayList<SkipListNode> nextNodes;
//code中,小的是高层,大的是低层
public SkipListNode(Integer value){
this.value = value;
nextNodes = new ArrayList<SkipListNode>();
}
}
public static class SkipListIterator implements Iterator<Integer>{
SkipList list;
SkipListNode current;
public SikpListIterator(SkipList list){
this.list = list;
this.current = list.getHead();
}
public boolean hasNext(){
return current.nextNodes.get(0) != null;
}
public Integer next(){
current = current.nextNodes.get(0);
return current.value;
}
}
public static class SkipList{
//head是巨小
private SkipListNode head;
private int maxLevel;//所有数据roll出来的最大层
private int size;//加进来的所有数据个数
private static final double PROBABILITY = 0.5;//roll的概率是多少
//
public SkipList(){
size = 0;
maxLevel = 0;
head = new SkipListNode(null);
head.nextNodes.add(null);
}
public SkipListNode getHead(){
return head;
}
public void add(Integer newValue){
if(!contains(newValue)){
size++;
int level =0;
while(Math.random()<PROBABILITY){
level++;
}
//当当前高度大于现在的最大高度,则进行扩充层数
while(level > maxLevel){
head.nextNodes.add(null);
maxLevel ++;
}
SkipListNode newNode = new SkipListNode(newvalue);
SkipListNode current = head;
do{
//current为当前层中最后一个小于newValue的
current = findNext(newValue,current,level);
//从第0层开始放,数据会从第0层一路向上,每一次在0层存入值,之前的值会向上升,最终将当前的节点的所有信息从第0行到随机的最高的一行全部存入信息。
newNode.nextNodes.add(0,current.nextNodes.get(level));
//将current第某个level上放的是newNode
current.nextNodes.set(level,newNode);
}while(level-->0);
}
}
public void delete(Integer deleteValue){
if(contains(deleteValue)){
SkipListNode deleteNode = find(deletevalue);
size--;
int level = maxLevel;
SkipListNode current = head;
do{
current = findNext(deleteNode.value,current,level);
if(deleteNode.nextNodes.size()>level){
current.nextNodes.set(level,deleteNode.nextNodes.get(level));
}
}while(level-->0);
}
}
//
private SkipListNode find(Integer e){
return find(e,head,maxLevel);
}
//
private SkipListNode find(Integer e,SkipListNode current,int level){
do{
current = findNext(e,current,level);
}while(level-->0);
return current;
}
//返回的current是在当前层中最后一个数小于当前key的值的
private SkipListNode findNext(Integer e,SkipListNode current,int level){
//得到当前level层的链表中的下一个节点,
SkipListNode next = current.nextNodes.get(level);
while(next != null){
Integer value = next.value;
if(lessThan(e,value)){//如果当前的值小于value,则直接跳出
break;
}
current = next;
next = current.nextNodes.get(level);
}
return current;
}
public int size(){
return size;
}
public boolean contains(Integer value){
SkipListNode node = find(value);
return node != null && node.value != null && equalTo(node.value,value);
}
public Ierator<Integer> iterator(){
return new SkipListIterator(this);
}
private boolean lessThan(Integer a,Integer b){
return a.compareTo(b) <0;
}
private boolean equalTo(Integer,a,Integer b){
return a.compareTo(b) == 0;
}
}