左神算法笔记(二十三)——跳表

跳表可以认为同样包含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;
	}
}

你可能感兴趣的:(左神算法专栏)