zoukankan      html  css  js  c++  java
  • 跳表实现

    跳表

    基于链表改造,增加多层索引链表,使得查找结点的平均时间复杂度为O(logn),但是增加了空间复杂度,采用双向链表,每层首尾各有一个空结点,左侧为负无穷大,右侧为正无穷大

    查找

    从最上层索引开始查找,找到该层中仅小于目标结点的前置索引节点,然后找下一层,一直到找到为止

    插入

    先找到待插入结点的前置结点,然后将该结点插入前置结点的下一个位置,同时需要调整索引,让新插入的结点随机成为索引结点,成功率为50%,如果到最高层还成功,直接增加一层索引

    删除

    先找到待删除的结点,将该结点删除,同时需要删除索引结点,如果某一层被删完了,直接删掉该层

    实现代码

    public class SkipList {
        //新插入结点成为索引结点的概率
        private static final double PROMOTE_RATE = 0.5;
        private Node head,tail;
        private int maxLevel;
    
        public SkipList() {
            //头节点是负无穷大,尾结点正无穷大
            head = new Node(Integer.MIN_VALUE);
            tail = new Node(Integer.MAX_VALUE);
            head.right = tail;
            tail.left = head;
        }
    
        //查找某个结点
        public Node search(int data){
            Node p= findNode(data);
            if(p.data == data){
                System.out.println("找到结点:" + data);
                return p;
            }
            System.out.println("未找到结点:" + data);
            return null;
        }
    
        //查找某个结点
        private Node findNode(int data){
            Node node = head;
            while(true){
                //从该层向右查找
                while (node.right.data!=Integer.MAX_VALUE && node.right.data<=data) {
                    node = node.right;
                }
                //如果没有下一层跳出循环
                if (node.down == null) {
                    break;
                }
                //到下一层
                node = node.down;
            }
            return node;
        }
    
        //插入结点
        public void insert(int data){
            //1.先查找前置结点
            Node preNode= findNode(data);
            //如果data相同,直接返回
            if (preNode.data == data) {
                return;
            }
            Node node=new Node(data);
            //2.添加新结点
            appendNode(preNode, node);
            int currentLevel=0;
            //随机决定结点是否“晋升”
            Random random = new Random();
            while (random.nextDouble() < PROMOTE_RATE) {
                //如果当前层已经是最高层,需要增加一层
                if (currentLevel == maxLevel) {
                    addLevel();
                }
                //找到上一层的前置节点
                while (preNode.up==null) {
                    preNode=preNode.left;
                }
                preNode=preNode.up;
                //把“晋升”的新结点插入到上一层
                Node upperNode = new Node(data);
                appendNode(preNode, upperNode);
                upperNode.down = node;
                node.up = upperNode;
                node = upperNode;
                currentLevel++;
            }
        }
    
        //在前置结点后面添加新结点
        private void appendNode(Node preNode, Node newNode){
            newNode.left=preNode;
            newNode.right=preNode.right;
            preNode.right.left=newNode;
            preNode.right=newNode;
        }
    
        //增加一层
        private void addLevel(){
            maxLevel++;
            Node p1=new Node(Integer.MIN_VALUE);
            Node p2=new Node(Integer.MAX_VALUE);
            p1.right=p2;
            p2.left=p1;
            p1.down=head;
            head.up=p1;
            p2.down=tail;
            tail.up=p2;
            head=p1;
            tail=p2;
        }
    
        //删除结点
        public boolean remove(int data){
            //1.查找待删除结点
            Node removedNode = search(data);
            if(removedNode == null){
                return false;
            }
    
            int currentLevel=0;
            while (removedNode != null){
                removedNode.right.left = removedNode.left;
                removedNode.left.right = removedNode.right;
                //如果不是最底层,且只有无穷小和无穷大结点,删除该层
                if(currentLevel != 0 && removedNode.left.data == Integer.MIN_VALUE && removedNode.right.data == Integer.MAX_VALUE){
                    removeLevel(removedNode.left);
                }else {
                    currentLevel ++;
                }
                removedNode = removedNode.up;
            }
    
            return true;
        }
    
        //删除一层
        private void removeLevel(Node leftNode){
            Node rightNode = leftNode.right;
            //如果删除层是最高层
            if(leftNode.up == null){
                leftNode.down.up = null;
                rightNode.down.up = null;
            }else {
                leftNode.up.down = leftNode.down;
                leftNode.down.up = leftNode.up;
                rightNode.up.down = rightNode.down;
                rightNode.down.up = rightNode.up;
            }
            maxLevel --;
        }
    
        //输出底层链表
        public void printList() {
            Node node=head;
            while (node.down != null) {
                node = node.down;
            }
            while (node.right.data != Integer.MAX_VALUE) {
                System.out.print(node.right.data + " ");
                node = node.right;
            }
            System.out.println();
        }
    
        //链表结点类
        public class Node {
            public int data;
            //跳表结点上下前后都有指针
            public Node up, down, left, right;
    
            public Node(int data) {
                this.data = data;
            }
        }
    }
    
  • 相关阅读:
    详解Python模块导入方法
    第15天上课例子,sqllchemy运用
    【Demo 0075】获取系统进程列表
    【Demo 0076】获取进程中模块列表
    【Demo 0071】托盘小工具
    【Demo 0070】读取EXE\DLL中ICON
    【Demo 0073】复合文件拼拆
    【Demo 0072】启动外部应用程序
    【Demo 0078】获取系统版本信息
    【Demo 0079】进程继承关系
  • 原文地址:https://www.cnblogs.com/jordan95225/p/13552651.html
Copyright © 2011-2022 走看看