著名开源软件Redis使用跳表。
一种随机化的数据结构,基于并联的链表,查询效率可以比拟二叉查找树,对于大多数操作需要O(logn)时间
基本思想:在有序的链表上,附加前进链接。
(1)跳表由多层组成
(2)每一层都是有序的链表
(3)第一层包含所有元素
(4)如果x出现在第i层,所有比i小的层都包含x
(5)第i层的元素通过一个down指针指向下一层拥有相同值的元素
(6)在每一层中都包含-1和1两个元素,分别表示INT_MIN和INT_MAX
(7)Top指针指向最高层的第一个元素
STEP1:查找到每一层的待插入位置
STEP2:随机产生一个层数
STEP3:从高层往下插入,插入算法与普通链表相同。
删除操作与插入类似,找到每一层需要删除的位置,之后删除操作与普通链表一样。
注:如果该结点层数最大,需要更新跳表的level。
成员变量:value 记录值
nextnodes[i] 表示第i层的下一个结点
成员函数:level() 记录最高层数
import java.util.ArrayList;
import java.util.List;
public class SkipListNode {
private E value;
public List > nextnodes; //每一层的下一个结点集合
public E getValue() {
return value;
}
public SkipListNode(E data){
this.value = data;
nextnodes = new ArrayList<>();
}
public int level(){
return nextnodes.size()-1;
}
public String toString(){
return "SLN:"+this.value;
}
}
定义一些接口
import java.util.AbstractSet;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
public abstract class AbstractSortedSet
extends AbstractSet implements SortedSet {
public E first(){
return null;
}
public E last(){
return null;
}
public Iterator iterator(){
return null;
}
public SortedSet headSet(E toElement){
return null;
}
public SortedSet tailSet(E fromElement){
return null;
}
public SortedSet subSet(E fromElement, E toElement){
return null;
}
public Comparator super E> comparator(){
return null;
}
}
成员变量:head 头部结点(指向最高层)
maxLevel 最高层数
size 记录总共的元素个数
成员函数:
findnext:在第level层,查找到e的前一个结点(在第level层遍历查找)
find:从最高层开始,使用findnext函数找到e前面的结点,层数减1,重复前面步骤,直到找到e
contain:调用find查找,比较e与查找到的元素
add:元素插入(随机产生一个层数,如果大于maxLevel,在超过的层数插入一个空结点; 从最高层开始往下,使用findnext哈函数找到这一层(设为第i层)的插入位置,newNode.nextNode[i]=curNode.nextnode[i], curNode.nextNode[i]=newNode)
import java.util.AbstractList;
import java.util.Arrays;
public class SkipList > extends AbstractSortedSet{
private SkipListNode head; //头部结点
private int maxLevel;
private int size; //记录元素数量
private static final double PROBABILITY = 0.5;
public SkipList(){
size = 0;
maxLevel = 0;
head = new SkipListNode<>(null);
head.nextnodes.add(null); //null标志结束
}
public SkipListNode getHead(){
return head;
}
/**
* 添加一个node(e)到SkipList
* @param e
* @return
*/
public boolean add(E e){
if (contains(e))
return false;
size ++;
//随机产生一个层数
int level = 0;
while(Math.random() < PROBABILITY)
level ++;
while(level > maxLevel){
head.nextnodes.add(null);
maxLevel ++;
}
SkipListNode newNode = new SkipListNode(e);
SkipListNode curNode = head;
//对每一层执行插入操作
do{
curNode = findNext(e, curNode, level);
//执行插入操作
newNode.nextnodes.add(0,curNode.nextnodes.get(level));
curNode.nextnodes.set(level, newNode);
level --;
}while (level >= 0);
return true;
}
/**
* 从level层到0层,从当前结点,搜索node(e)
* @param e
* @return
*/
private SkipListNode find(E e, SkipListNode curNode, int level){
do{
curNode = findNext(e, curNode, level);
level--;
}while (level >= 0);
return curNode;
}
/**
* 全部层(从上到下)搜索node(e)
* @param e
* @return
*/
public SkipListNode find(E e){
return find(e, head, maxLevel);
}
/**
* 在level下,寻找到node(e)位置的前一个结点
* @param e 插入node的值
* @param curNode 当前结点开始搜索
* @param level
* @return e插入位置的前一个结点
*/
public SkipListNode findNext(E e, SkipListNode curNode, int level){
SkipListNode nextNode = (SkipListNode)curNode.nextnodes.get(level);
while (nextNode != null){
E value = nextNode.getValue();
if(lessThan(e, value)) //e node = find(e);
return (node!=null && node.getValue()!=null && equalTo(e, node.getValue()));
}
@Override
public int size() {
return size;
}
/**
* 得到SkipList的迭代器
* @return
*/
public SkipListIterator iterator(){
return new SkipListIterator<>(this);
}
private boolean lessThan(E a, E b){
return a.compareTo(b) < 0;
}
private boolean equalTo(E a, E b) {
return a.compareTo(b) == 0;
}
private boolean greaterThan(E a, E b) {
return a.compareTo(b) > 0;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("SkipList: ");
for(Object o : this)
builder.append(o).append(", ");
String s = builder.toString();
return s.substring(0,s.length()-2);
}
}
成员变量:list 迭代器类中保存一个SkipList实例
curNode 当前指向的结点
成员函数:next:curNode=curNode.nextNode[0](第0层包含所有元素)
hasnext:判断curNode.nextNode[0]是否为空结点
import java.util.Iterator;
public class SkipListIterator >
implements Iterator {
SkipList list;
SkipListNode curNode;
public SkipListIterator(SkipList list){
this.list = list;
this.curNode = list.getHead();
}
@Override
public boolean hasNext() {
return curNode.nextnodes.get(0) != null;
}
@Override
public E next() {
curNode = curNode.nextnodes.get(0);
return curNode.getValue();
}
public void remove(){
throw new UnsupportedOperationException();
}
}