跳表的java实现

跳表的java实现

节点的定义

/**
 * 跳表节点定义
 */
@Data
@AllArgsConstructor
public class SkipNode<T> {

    int key;
    T val;
    SkipNode next, down;

    public SkipNode(int key, T val) {
        this.key = key;
        this.val = val;
    }
}

跳表

public class SkipList {

    SkipNode head;

    //支持的最大层数
    public static final int MAX_LEVEL = 10;

    int highLevel;//当前队列的最大层数

    public SkipList(){
        head = new SkipNode<>(Integer.MIN_VALUE,null);
        highLevel = 0;
    }


    /**
     * 返回随机层数
     */
    public int getRandomLevel()
    {
        int lev = 1;
        while(RandomUtil.randomInt()%2==0 &&lev< MAX_LEVEL )
        {
            lev++;
        }

        return lev;
    }

    /**
     * 查询节点是否存在,存在则返回节点
     * 思路:能往右走就往右走,不能就往下
     */
    public SkipNode search(int key)
    {
        SkipNode tar = head;

        while(tar!=null)
        {
            if(tar.getKey()==key)
            {
                break;
            }
            if(tar.next==null) tar = tar.down;
            else if(tar.next.getKey()>key) tar = tar.down;
            else tar = tar.next;
        }
        return tar;

    }

    /**
     * 查询key的值
     */
    public Object get(int key)
    {
        SkipNode tar = head;

        while(tar!=null)
        {
            if(tar.getKey()==key)
            {
               break;
            }
            if(tar.next==null) tar = tar.down;
            else if(tar.next.getKey()>key) tar = tar.down;
            else tar = tar.next;
        }
        if(tar!=null) return tar.getVal();
        else return null;

    }


    /**
     * 插入
     * 思路:先判断 节点是否存在,不存在就生成随机高度,然后找到每一层的前驱节点
     * 因为每一个节点都需要有个往下的节点,所以要从下往上插入
     */
    public void put(int key, Object val)
    {

        SkipNode tmp = head;

        //之后要找到 新节点在每一层的前驱节点,然后由下而上地新增
        List<SkipNode> pre = new ArrayList<>();
        //判断key是否已经存在
        SkipNode tar =search(key) ;
        if(tar!=null)
        {
            //存在,则将该节点所有层都刷新val
            while(tar!=null)
            {
                tar.setVal(val);
                tar = tar.down;
            }
            return;
        }

        int lev = getRandomLevel();//随机生成
        System.out.println("当前key为 "+key +  ",当前节点层数 "+lev);
        //如果当前lev 是整个跳表最高值,那么头节点也要增加层数
        for(int i=highLevel+1;i<=lev;i++)
        {
            tmp = new SkipNode<>(Integer.MIN_VALUE,null);

            tmp.next = null;
            tmp.down = head;
            head = tmp;
        }
        highLevel = Math.max(lev,highLevel);


        tmp = head;
        int cnt = highLevel;
        //要找到对应层数的开始节点
        while(cnt!=lev)
        {
            tmp = tmp.down;
            cnt--;
        }

        //寻找前驱节点
        while(tmp!=null)
        {
            if(tmp.getKey() ==key)
            {
                tmp.setVal(val);

                tmp = tmp.down;
            }
            else if(tmp.next==null)
            {
                //因为list实际上存的是引用,所以要复制一份再存进去
                SkipNode x = tmp;
                pre.add(x);
                tmp = tmp.down;
            }
            else if(tmp.next.getKey()>key)
            {
                SkipNode x = tmp;
                pre.add(x);
                tmp = tmp.down;
            }
            else {
                tmp = tmp.next;
            }
        }

        //由下而上新增节点
        SkipNode down = null;
        for(int i=pre.size()-1;i>=0;i--)
        {
            SkipNode node = new SkipNode<>(key,val);
            node.down = down;
            pre.get(i).next = node;
            down = node;
        }

    }

    public void delete(int key)
    {
        SkipNode tmp = head;

        while(tmp!=null)
        {
            if(tmp.next==null) tmp = tmp.down;
            else if(tmp.next.getKey()==key)
            {
                tmp.next = tmp.next.next;
                tmp = tmp.down;
            }
            else if(tmp.next.getKey()<key) tmp = tmp.next;
            else tmp = tmp.down;
        }
    }

    public void print()
    {

        SkipNode tmp = head;

        while(tmp!=null)
        {
            SkipNode now = tmp;
            while(now!=null)
            {
                System.out.print("["+now.getKey()+" "+now.getVal()+"]");
                System.out.print("  ");
                now = now.next;
            }
            System.out.println();
            tmp = tmp.down;
        }

    }

    public static void main(String[] args) {
        SkipList skipList = new SkipList();

        skipList.put(1,10);
        skipList.put(1,11);
        skipList.put(2,12);
        skipList.put(3,11);
        skipList.put(3,15);
        skipList.put(4,14);

        skipList.delete(1);
        System.out.println(skipList.get(3));
        skipList.print();

    }
}

posted @ 2024-05-28 15:54  Liang2003  阅读(2)  评论(0编辑  收藏  举报