数据结构-跳表

著名开源软件Redis使用跳表。

跳表

一种随机化的数据结构,基于并联的链表,查询效率可以比拟二叉查找树,对于大多数操作需要O(logn)时间

基本思想:在有序的链表上,附加前进链接。

数据结构-跳表_第1张图片

跳表的特征:

(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 {
    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;
    }
}

AbstractSoretedSet类:继承AbstractSet类,实现SortedSet接口

定义一些接口

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 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 > 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);
    }
}

SkipListIterator类:继承Comparable类,实现Iterator接口

成员变量: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();
    }
}

 

你可能感兴趣的:(java,数据结构)