著名开源软件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。
代码实现:
SkipListNode类:
成员变量:value 记录值
nextnodes[i] 表示第i层的下一个结点
成员函数:level() 记录最高层数
import java.util.ArrayList;
import java.util.List;
public class SkipListNode<E> {
private E value;
public List<SkipListNode<E> > 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;
}
}
AbstractSoretedSet类:继承AbstractSet类,实现SortedSet接口
定义一些接口
import java.util.AbstractSet;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
public abstract class AbstractSortedSet<E>
extends AbstractSet<E> implements SortedSet<E> {
public E first(){
return null;
}
public E last(){
return null;
}
public Iterator<E> iterator(){
return null;
}
public SortedSet<E> headSet(E toElement){
return null;
}
public SortedSet<E> tailSet(E fromElement){
return null;
}
public SortedSet<E> subSet(E fromElement, E toElement){
return null;
}
public Comparator<? super E> comparator(){
return null;
}
}
SkipList类:继承AbstractSortedSet类
成员变量: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<E extends Comparable<E> > extends AbstractSortedSet<E>{
private SkipListNode<E> 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<E> 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>(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<E> curNode, int level){
SkipListNode<E> nextNode = (SkipListNode<E>)curNode.nextnodes.get(level);
while (nextNode != null){
E value = nextNode.getValue();
if(lessThan(e, value)) //e<value
break;
curNode = nextNode;
nextNode = curNode.nextnodes.get(level);
}
return curNode;
}
public boolean contains(E e){
SkipListNode<E> node = find(e);
return (node!=null && node.getValue()!=null && equalTo(e, node.getValue()));
}
@Override
public int size() {
return size;
}
/**
* 得到SkipList的迭代器
* @return
*/
public SkipListIterator<E> 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);
}
}
SkipListIterator类:继承Comparable类,实现Iterator接口
成员变量:list 迭代器类中保存一个SkipList实例
curNode 当前指向的结点
成员函数:next:curNode=curNode.nextNode[0](第0层包含所有元素)
hasnext:判断curNode.nextNode[0]是否为空结点
import java.util.Iterator;
public class SkipListIterator<E extends Comparable<E> >
implements Iterator<E> {
SkipList<E> list;
SkipListNode<E> curNode;
public SkipListIterator(SkipList<E> 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();
}
}