数据结构跳跃表java版实现

跳跃表解释

代码实现(只实现了新增,打印和判断是否存在)

public class SkipList {
    private static class Node {
        Integer key;
        String value;
        Node up = null, down = null, left = null, right = null;

        public static Integer headKey = Integer.MIN_VALUE;  //  跳表左界限
        public static Integer tailKey = Integer.MAX_VALUE; //  跳表右界限

        public Node(Integer key, String value) {
            this.key = key;
            this.value = value;
        }
    }

    //头结点 (最高层)
    private Node head;

    //尾结点 (最高层)
    private Node tail;

    //跳表层数
    private Integer level;

    //元素数
    private Integer size;

    private Random random; //随机投掷硬币

    private static final double PROBABILITY = 0.5;//向上提升一个的概率


    {
        head = new Node(Node.headKey, null);
        tail = new Node(Node.tailKey, null);
        size = 0;
        head.right = tail;
        tail.left = head;
        random = new Random();
        level = 0;
    }

    /**
     * 判断是否存在此key
     *
     * @param key
     * @return
     */
    public Boolean contain(Integer key) {
        Node node = find(key);
        if (node.key.equals(key)) {
            return true;
        }
        return false;
    }

    public void put(Integer key, String value) {
        //找到插入位置的前一个节点(由于只有最后一层有数据域 所以find(key)查询的插入点 一定在最后一层)
        Node p = find(key);
        //已存在就不处理
        if (p.key == key) {
            return;
        }
        //往底层插入节点 所以不需要连接'down'
        // 因为是刚插入的节点所以以前底层是没有此节点的,
        // 根据跳跃表的特性底层没有该节点,上层肯定也没有,所以不需要连接'up'
        Node newNode = new Node(key, value);
        insertpre2aft(p, newNode);
        Integer currentLevel = 0;

        /*--------------至此跳表的元素插入以完成,接下来是跳表的底层元素向上提升-------------------*/

        //抛硬币决定刚插入的元素 是否向上加提升
        while (random.nextDouble() < PROBABILITY) {
            //如果当前层数为最高层
            if (currentLevel >= level) {
                //向上提升 总层级+1
                level++;
                //新建一层 首先是连接最新加入的头尾节点
                Node newHead = new Node(Node.headKey, null);
                Node newTail = new Node(Node.tailKey, null);
                //水平连接
                newHead.right = newTail;
                newTail.left = newHead;
                //上下连接
                insertUp2down(newHead, head);
                insertUp2down(newTail, tail);
                //全局变量head,tail表示的是最高层头尾节点,所以此时需要提升原头尾节点到最高层
                head = newHead;
                tail = newTail;

                /*---------------------在需要提升总层级的情况下,至此跳表的总层数上升了一层, 接下来提升元素---------------------------*/

            }




            //如果插入元素的前一个元素上面是null 则往左偏移找到上层
            while (null == p.up) {
                p = p.left;
            }
            p = p.up;


            //新建node并连接
            Node e = new Node(key, null);
            insertpre2aft(p, e);
            insertUp2down(e, newNode);
            newNode = e;
            currentLevel++;

        }
        size++;


    }


    /**
     * 插入时查找插入位置的前一个位置
     */
    private Node find(Integer key) {
        Node p = head;
        //确保从上到下每级向右查找
        while (true) {
            //当前级向右查找,直到找到表里的key大于或等于传入的key
            while (p.right.key != tail.key && p.right.key <= key) {
                p = p.right;
            }
            //跳出循环开始下跳一级 先判断是否有下一级
            if (null != p.down) {
                p = p.down;
            } else {
                return p;
            }
        }
    }


    /**
     * p后水平插入q
     *
     * @param p
     * @param q
     */
    private void insertpre2aft(Node p, Node q) {
        Node qnext = null;
        qnext = p.right;

        p.right = q;
        q.left = p;
        qnext.left = q;
        q.right = qnext;

    }
    
    private void insertUp2down(Node up, Node down) {
        up.down = down;
        down.up = up;
    }

    /**
     * 打印
     */
    public void print() {
        Node tempHead = head;
        Node tempTail = tail;

        Node p = tempHead;
        StringBuilder sb = new StringBuilder();
        while (true) {
            while (p.right != tempTail) {
                p = p.right;

                sb = sb.append(p.key).append("  ");
            }
            p = tempHead;
            if (null == p.down) {
                System.out.println(sb);
                return;
            }
            tempHead = tempHead.down;
            tempTail = tempTail.down;
            p = p.down;
            System.out.println(sb);
            sb.delete(0,sb.length());
        }
    }

    public static void main(String[] args) {
        SkipList skipList = new SkipList();
        for (int i = 1; i <= 1000; i++) {
            skipList.put(i, null);
        }
        skipList.print();


    }
}

控制台输出

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值