跳表的java实现

首先贴出参考的博客:

https://blog.csdn.net/moakun/article/details/79997037

根据这篇博客的代码自己实现了一个,添加了删除模块。
如果有理论不懂的可以看上面的博客也可以看下面的视频:

https://www.bilibili.com/video/BV1z7411f7mE?from=search&seid=17814720194061062383

下面是我的代码,代码中有详细的注释,我就不在赘述:

import java.util.Random;

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉
 *
 * @author Administrator
 * @create 2020/04/13
 * @since 1.0.0
 */
public class SkipListTest {
    //跳表的层数,默认为1
    private int skiplevel = 1;
    //最大值,为尾部的key
    private int maxint = Integer.MAX_VALUE;
    //最小值,为头部的key
    private int minint = Integer.MIN_VALUE;
    //跳表的头结点和尾节点
    private SkipNode head = null,tail = null;
    //随机对象,用于随机的判断当前的节点需不需要升层
    private Random random = null;
    //随机值判断的标志
    private double isup = 0.5;
    //节点数
    private int nodes = 0;
    public SkipListTest(){
        clear();
    }

    /**
     * 重置当前的状态
     */
    public void clear(){
        //重置层数
        setSkiplevel(1);
        //设置随机对象
        setRandom(new Random());
        //设置头
        setHead(new SkipNode(getMinint(),null));
        //设置尾
        setTail(new SkipNode(getMaxint(),null));
        //连接头尾
        UpLink(getHead(),getTail());
    }
    /**
     * 从中间断开
     * node1-right-*-left-node3
     * node1-right-*-left-node2-right-*-left-node3
     * @param node1  已存在的节点
     * @param node2  已存在节点后面要插入的节点
     */
    public void LeftAndRight(SkipNode node1,SkipNode node2){
        SkipNode node3 = node1.getRight();
        node2.setLeft(node1);
        node2.setRight(node3);
        node1.setRight(node2);
        node3.setLeft(node2);
    }

    /**
     *  node1-right-*-left-node-right-*-left-node2
     *  node1-right-*-left-node2
     * @param Node  需要删除的节点
     */
    public void NoLeftAndRight(SkipNode Node){
        SkipNode leftsn = Node.getLeft();
        SkipNode rightsn = Node.getRight();
        leftsn.setRight(rightsn);
        rightsn.setLeft(leftsn);
        System.out.println(Node.toString()+"   已删除");
        //如果删除了这个元素后本层只剩下了头和尾并且当前的层数是大于1的,那么将本层也删掉
        if(leftsn.getRight().getKey() == getMaxint() && leftsn.getKey() == minint&&getSkiplevel()>1){
            System.out.println("此层需要被删除");
            //断开连接
            leftsn.setRight(null);
            rightsn.setLeft(null);
            //重新对head和tail赋值
            setHead(leftsn.getDown());
            setTail(rightsn.getDown());
            //取消对上层的引用
            getHead().setUp(null);
            getTail().setUp(null);
            //层数减一
            setSkiplevel(getSkiplevel()-1);
        }
    }

    /**
     * node2
     *  |
     * down
     *  |
     *  *
     *  |
     * up
     *  |
     * node1
     * @param node1  当前存在的节点
     * @param node2  将要作为当前节点的上面节点的节点
     */
    public void UpAndDown(SkipNode node1,SkipNode node2){
        node1.setUp(node2);
        node2.setDown(node1);
    }

    /**
     * 专门连接两端的函数,即head --left --*--right --tail
     * node1-right-*-left-node2
     * @param node1  前一个节点
     * @param node2  后一个节点
     */
    public void UpLink(SkipNode node1,SkipNode node2){
        node1.setRight(node2);
        node2.setLeft(node1);
    }

    /**
     *  head ---------------------tail
     *  |                           |
     *  head --------node1--------tail
     *  |              |            |
     *  head --node2-node1--node3-tail
     *  |         |    |       |    |
     *  head-n4-node2-node1-node3-tail
     * @param key  需要匹配的key
     * @return
     */
    public SkipNode FindSkipNode(int key){
        SkipNode sn = getHead();
         System.out.println("************查找,当前查找的key为 "+key);
        while(true){
            while (sn.getRight().getKey() != getMaxint()&&sn.getRight().getKey()<=key){
                sn = sn.getRight();
                System.out.println("向右走"+sn.toString());
            }
            //向下走
            if(sn.getDown() != null){
                sn = sn.getDown();
                System.out.println("向下走"+sn.toString());
            }else break;   //要么找到了,要么表示没有数据
        }
        return sn;
    }

    /**
     *  1.先查找到需要插入的地方
     *  2.执行插入
     *  3.判定需不需要进行升层
     * @param key    插入节点的key
     * @param value  插入节点的value
     */
    public void AddSkipNode(int key,String value){
        SkipNode sn = FindSkipNode(key);
        if(sn.getKey() == key){
            sn.setValue(value);
            return;
        }else{
            //1.创建出节点
            SkipNode skipNode = new SkipNode(key,value);
            //2.插入节点
            LeftAndRight(sn,skipNode);
            //用作判定是否超过现有的层数
            int currentlevel = 1;
            //3.判定需不需要进行升层,使用抛硬币的方法,1/2的概率
            double v = getRandom().nextDouble();
            System.out.println("  当前的节点  "+skipNode.toString());
            while(v<=getIsup()){
                System.out.println("需要升层");
                //1.首先判断currentlevel是否超过了现有的层数
                if(currentlevel>=getSkiplevel()){
                    System.out.println("需要建立一个新的层次");
                    //2.此时先提高层数
                    setSkiplevel(getSkiplevel()+1);
                    //3.创建出两端的副本
                    SkipNode snhead = new SkipNode(getMinint(),null);
                    SkipNode sntail = new SkipNode(getMaxint(),null);
                    //4.水平上的连接
                    UpLink(snhead,sntail);
                    //5.上下的承接
                    UpAndDown(getHead(),snhead);
                    UpAndDown(getTail(),sntail);
                    //6.赋值
                    setHead(snhead);
                    setTail(sntail);
                }
                //7.找到祖静的可以到上一层的节点
                //如果本节点就是那么直接跳过
                while(sn.getUp() == null){
                    sn = sn.getLeft();
                    System.out.println("向左走,找到最靠近的多层节点  "+sn.toString());
                }
                //得到上一层
                sn = sn.getUp();
                System.out.println("找到上层节点,开始构建层次,当前的层次为 "+currentlevel);
                //8.新建关于当前插入节点的上层节点
                SkipNode skipNodeUP = new SkipNode(key, null);
                //插入节点
                LeftAndRight(sn,skipNodeUP);
                //层次关系
                UpAndDown(skipNode,skipNodeUP);
                //赋值
                skipNode = skipNodeUP;

                v = getRandom().nextDouble();
                //加层
                currentlevel++;
                System.out.println("构建完成,当前的节点的层次为 "+currentlevel);
            }
            if (currentlevel == 0)
                System.out.println("当前节点不需要构建层次");
            //节点数加一
            setNodes(getNodes()+1);
        }
    }

    /**
     *  1.先查找到需要删除的key
     *  2.如果没有就返回
     *  3.找到后从底向上开始删除
     * @param key 要删除的节点的key
     */
    public boolean DeleteSkipNode(int key){
        SkipNode sn = FindSkipNode(key);
        if(sn.getKey()!=key)
            return false;
        else{
            while(sn != null){
                NoLeftAndRight(sn);
                sn = sn.getUp();
                System.out.println("开始删除上层节点");
            }
            //节点数减一
            setNodes(getNodes()-1);
            return true;
        }
    }

    public int getSkiplevel() {
        return skiplevel;
    }

    public void setSkiplevel(int skiplevel) {
        this.skiplevel = skiplevel;
    }

    public int getMaxint() {
        return maxint;
    }

    public void setMaxint(int maxint) {
        this.maxint = maxint;
    }

    public int getMinint() {
        return minint;
    }

    public void setMinint(int minint) {
        this.minint = minint;
    }

    public SkipNode getHead() {
        return head;
    }

    public void setHead(SkipNode head) {
        this.head = head;
    }

    public SkipNode getTail() {
        return tail;
    }

    public void setTail(SkipNode tail) {
        this.tail = tail;
    }

    public Random getRandom() {
        return random;
    }

    public void setRandom(Random random) {
        this.random = random;
    }

    public double getIsup() {
        return isup;
    }

    public void setIsup(double isup) {
        this.isup = isup;
    }

    public int getNodes() {
        return nodes;
    }

    public void setNodes(int nodes) {
        this.nodes = nodes;
    }
}

class SkipNode{
    //左节点
    private SkipNode left = null;
    //右结点
    private SkipNode right = null;
    //上节点
    private SkipNode up = null;
    //下节点
    private SkipNode down = null;
    //key值
    private int key = 0;
    //value值
    private String value = null;
    public SkipNode(int key,String value){
        this.key = key;
        this.value = value;
    }

    public SkipNode getLeft() {
        return left;
    }

    public void setLeft(SkipNode left) {
        this.left = left;
    }

    public SkipNode getRight() {
        return right;
    }

    public void setRight(SkipNode right) {
        this.right = right;
    }

    public SkipNode getUp() {
        return up;
    }

    public void setUp(SkipNode up) {
        this.up = up;
    }

    public SkipNode getDown() {
        return down;
    }

    public void setDown(SkipNode down) {
        this.down = down;
    }

    public int getKey() {
        return key;
    }

    public void setKey(int key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "SkipNode{" +
                "value=" + value +
                ", key='" + key + '\'' +
                '}';
    }
}
class runstart{
    public static void main(String[] args) {
        SkipListTest list=new SkipListTest();
        System.out.println(list);
        list.AddSkipNode(2, "yan");
        list.AddSkipNode(1, "co");
        list.AddSkipNode(3, "feng");
        list.AddSkipNode(1, "cao");//测试同一个key值
        list.AddSkipNode(4, "曹");
        list.AddSkipNode(6, "丰");
        list.AddSkipNode(5, "艳");
        System.out.println(list);
        StringBuilder stringBuilder = new StringBuilder();
        System.out.println("当前的跳表的层数为 "+list.getSkiplevel());
        System.out.println("当前跳表的元素个数为 "+list.getNodes());
        boolean b = list.DeleteSkipNode(1);
        if(b){
            SkipNode head = list.getHead();
            while (head.getDown()!=null)
                head = head.getDown();
            if(head.getRight().getKey()!=list.getTail().getKey()){
                head = head.getRight();
            }
            System.out.println("当前的跳表的层数为 "+list.getSkiplevel());
            System.out.println("当前跳表的元素个数为 "+list.getNodes());
            System.out.println("删除成功");
            stringBuilder.delete(0,stringBuilder.length());
            while(head.getRight().getKey()!=list.getTail().getKey()){
                stringBuilder.append(head.toString());
                stringBuilder.append("\n");
                head = head.getRight();
            }
            System.out.println(stringBuilder.toString());
        }
    }
}

效果:
笔试.SkipListTest@74a14482
************查找,当前查找的key为 2
当前的节点 SkipNode{value=yan, key=‘2’}
需要升层
需要建立一个新的层次
找到上层节点,开始构建层次,当前的层次为 1
构建完成,当前的节点的层次为 2
需要升层
需要建立一个新的层次
找到上层节点,开始构建层次,当前的层次为 2
构建完成,当前的节点的层次为 3
************查找,当前查找的key为 1
向下走SkipNode{value=null, key=’-2147483648’}
向下走SkipNode{value=null, key=’-2147483648’}
当前的节点 SkipNode{value=co, key=‘1’}
需要升层
找到上层节点,开始构建层次,当前的层次为 1
构建完成,当前的节点的层次为 2
需要升层
找到上层节点,开始构建层次,当前的层次为 2
构建完成,当前的节点的层次为 3
************查找,当前查找的key为 3
向右走SkipNode{value=null, key=‘1’}
向右走SkipNode{value=null, key=‘2’}
向下走SkipNode{value=null, key=‘2’}
向下走SkipNode{value=yan, key=‘2’}
当前的节点 SkipNode{value=feng, key=‘3’}
************查找,当前查找的key为 1
向右走SkipNode{value=null, key=‘1’}
向下走SkipNode{value=null, key=‘1’}
向下走SkipNode{value=co, key=‘1’}
************查找,当前查找的key为 4
向右走SkipNode{value=null, key=‘1’}
向右走SkipNode{value=null, key=‘2’}
向下走SkipNode{value=null, key=‘2’}
向下走SkipNode{value=yan, key=‘2’}
向右走SkipNode{value=feng, key=‘3’}
当前的节点 SkipNode{value=曹, key=‘4’}
************查找,当前查找的key为 6
向右走SkipNode{value=null, key=‘1’}
向右走SkipNode{value=null, key=‘2’}
向下走SkipNode{value=null, key=‘2’}
向下走SkipNode{value=yan, key=‘2’}
向右走SkipNode{value=feng, key=‘3’}
向右走SkipNode{value=曹, key=‘4’}
当前的节点 SkipNode{value=丰, key=‘6’}
需要升层
向左走,找到最靠近的多层节点 SkipNode{value=feng, key=‘3’}
向左走,找到最靠近的多层节点 SkipNode{value=yan, key=‘2’}
找到上层节点,开始构建层次,当前的层次为 1
构建完成,当前的节点的层次为 2
需要升层
找到上层节点,开始构建层次,当前的层次为 2
构建完成,当前的节点的层次为 3
************查找,当前查找的key为 5
向右走SkipNode{value=null, key=‘1’}
向右走SkipNode{value=null, key=‘2’}
向下走SkipNode{value=null, key=‘2’}
向下走SkipNode{value=yan, key=‘2’}
向右走SkipNode{value=feng, key=‘3’}
向右走SkipNode{value=曹, key=‘4’}
当前的节点 SkipNode{value=艳, key=‘5’}
需要升层
向左走,找到最靠近的多层节点 SkipNode{value=feng, key=‘3’}
向左走,找到最靠近的多层节点 SkipNode{value=yan, key=‘2’}
找到上层节点,开始构建层次,当前的层次为 1
构建完成,当前的节点的层次为 2
笔试.SkipListTest@74a14482
当前的跳表的层数为 3
当前跳表的元素个数为 6
************查找,当前查找的key为 1
向右走SkipNode{value=null, key=‘1’}
向下走SkipNode{value=null, key=‘1’}
向下走SkipNode{value=cao, key=‘1’}
SkipNode{value=cao, key=‘1’} 已删除
开始删除上层节点
SkipNode{value=null, key=‘1’} 已删除
开始删除上层节点
SkipNode{value=null, key=‘1’} 已删除
开始删除上层节点
当前的跳表的层数为 3
当前跳表的元素个数为 5
删除成功
SkipNode{value=yan, key=‘2’}
SkipNode{value=feng, key=‘3’}
SkipNode{value=曹, key=‘4’}
SkipNode{value=艳, key=‘5’}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值