【Java】跳跃表的实现以及用例测试

跳跃表
思想不再赘述,直接贴代码:
SkipListNode.java

package com.kuber.algorithmtest.skiplist;

public class SkipListNode <T>{
    
    
    private int key;
    private T value;
    public SkipListNode<T> up, down, left, right; // 上下左右 四个指针

    public static final int HEAD_KEY = Integer.MIN_VALUE; // 负无穷
    public static final int  TAIL_KEY = Integer.MAX_VALUE; // 正无穷

    public SkipListNode(int k, T v) {
    
    
        key = k;
        value = v;
    }
    public int getKey() {
    
    
        return key;
    }
    public void setKey(int key) {
    
    
        this.key = key;
    }
    public T getValue() {
    
    
        return value;
    }
    public void setValue(T value) {
    
    
        this.value = value;
    }
    public boolean equals(Object o) {
    
    
        if (this == o) {
    
    
            return true;
        }
        if (o == null) {
    
    
            return false;
        }
        if (!(o instanceof SkipListNode<?>)) {
    
    
            return false;
        }
        SkipListNode<T> ent;
        try {
    
    
            ent = (SkipListNode<T>) o; // 检测类型
        } catch (ClassCastException ex) {
    
    
            return false;
        }
        return (ent.getKey() == key) && (ent.getValue() == value);
    }
    @Override
    public String toString() {
    
    
        return "key=value:" + key + "=" + value;
    }
}

SkipList.java:

package com.kuber.algorithmtest.skiplist;

import java.util.Random;


public class SkipList <T>{
    
    

    private SkipListNode<T> head,tail;
    private int nodes; // 节点总数
    private int listLevel; // 最大层数
    private Random random; // 随机数,用于投掷硬币决定是否要加层高
    private static final double PROBABILITY = 0.25; // 向上提升一个的概率(此处采用redis中的默认值)
    private static final int MAXLEVEL = 32; // 最大层高(此处采用redis中的默认值)

    public SkipList() {
    
    
        random = new Random();
        clear();
    }

    /**
     * @Description: 清空跳跃表
     * @Param: []
     * @return: void
     * @Author: kuber
     */
    public void clear(){
    
    
        head = new SkipListNode<T>(SkipListNode.HEAD_KEY, null);
        tail = new SkipListNode<T>(SkipListNode.TAIL_KEY, null);
        horizontalLink(head, tail);
        listLevel = 0;
        nodes = 0;
    }

    public boolean isEmpty(){
    
    
        return nodes == 0;
    }

    public int size() {
    
    
        return nodes;
    }

    /**
     * @Description: 找到要插入的位置前面的那个key 的最底层节点
     * @Param: [key]
     * @return: com.jet.SkipListNode<T>
     * @Author: kuber
     */
    private SkipListNode<T> findNode(int key){
    
    
        SkipListNode<T> p = head;
        while(true){
    
    
            while (p.right.getKey() != SkipListNode.TAIL_KEY && p.right.getKey() <= key) {
    
    
                p = p.right;
            }
            if (p.down != null) {
    
    
                p = p.down;
            } else {
    
    
                break;
            }

        }
        return p;
    }

    /**
     * @Description: 查找是否存在key,存在则返回该节点,否则返回null
     * @Param: [key]
     * @return: com.wailian.SkipListNode<T>
     * @Author: kuber
     */
    public SkipListNode<T> search(int key){
    
    
        SkipListNode<T> p = findNode(key);
        if (key == p.getKey()) {
    
    
            return p;
        } else {
    
    
            return null;
        }
    }

    /**
     * @Description: 向跳跃表中添加key-value
     * @Param: [k, v]
     * @return: void
     * @Author: kuber
     */
    public void put(int k,T v){
    
    
        SkipListNode<T> p = findNode(k);
        // 如果key值相同,替换原来的value即可结束
        if (k == p.getKey()) {
    
    
            p.setValue(v);
            return;
        }
        SkipListNode<T> q = new SkipListNode<>(k, v);
        backLink(p, q);
        int currentLevel = 0; // 当前所在的层级是0
        // 抛硬币
        while (random.nextDouble() < PROBABILITY && currentLevel < MAXLEVEL) {
    
    
            // 如果超出了高度,需要重新建一个顶层
            if (currentLevel >= listLevel) {
    
    
                listLevel++;
                SkipListNode<T> p1 = new SkipListNode<>(SkipListNode.HEAD_KEY, null);
                SkipListNode<T> p2 = new SkipListNode<>(SkipListNode.TAIL_KEY, null);
                horizontalLink(p1, p2);
                verticalLink(p1, head);
                verticalLink(p2, tail);
                head = p1;
                tail = p2;
            }
            // 将p移动到上一层
            while (p.up == null) {
    
    
                p = p.left;
            }
            p = p.up;

            SkipListNode<T> e = new SkipListNode<>(k, null); // 只保存key就ok
            backLink(p, e); // 将e插入到p的后面
            verticalLink(e, q); // 将e和q上下连接
            q = e;
            currentLevel++;
        }
        nodes++; // 层数递增
    }

    /**
     * @Description: node1后面插入node2
     * @Param: [node1, node2]
     * @return: void
     * @Author: kuber
     */
    private void backLink(SkipListNode<T> node1,SkipListNode<T> node2){
    
    
        node2.left = node1;
        node2.right = node1.right;
        node1.right.left = node2;
        node1.right = node2;
    }

    /**
     * @Description: 水平双向连接
     * @Param: [node1, node2]
     * @return: void
     * @Author: kuber
     */
    private void horizontalLink(SkipListNode<T> node1,SkipListNode<T> node2){
    
    
        node1.right = node2;
        node2.left = node1;
    }

    /**
     * @Description: 垂直双向连接
     * @Param: [node1, node2]
     * @return: void
     * @Author: kuber
     */
    private void verticalLink(SkipListNode<T> node1, SkipListNode<T> node2){
    
    
        node1.down = node2;
        node2.up = node1;
    }

    @Override
    public String toString() {
    
    
        if (isEmpty()) {
    
    
            return "跳跃表为空!!!";
        }
        StringBuilder builder = new StringBuilder();
        SkipListNode<T> p=head;
        while (p.down != null) {
    
    
            p = p.down;
        }

        while (p.left != null) {
    
    
            p = p.left;
        }
        if (p.right!= null) {
    
    
            p = p.right;
        }
        while (p.right != null) {
    
    
            builder.append(p).append("\n");
            p = p.right;
        }

        return builder.toString();
    }

}

junit单元测试:

package com.kuber.algorithmtest.skiplist;

import org.junit.Test;

public class SkipListTest {
    
    

    @Test
    public void test1(){
    
    
        SkipList<String> list = new SkipList<>();
        System.out.println(list);
        System.out.println("添加数据:");
        list.put(6, "!!!");
        list.put(1, "Ni Wenhan");
        list.put(2, "make");
        list.put(3, "SkipList");
        list.put(1, "kuber");
        list.put(4, "come true");
        list.put(5, "successfully");
        System.out.println("遍历表:");
        System.out.println(list);
        System.out.println("表长为:"+list.size());
    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43215322/article/details/112170930
今日推荐