zoukankan      html  css  js  c++  java
  • jdk源码分析PriorityQueue

    一、结构

    PriorityQueue是一个堆,任意节点都是以它为根节点的子树中的最小节点
    堆的逻辑结构是完全二叉树状的,存储结构是用数组去存储的,随机访问性好。最小堆的根元素是最小的,最大堆的根元素是最大的
    dav
    这是一个最小堆的逻辑结构
    550265677348132602
    这是他的存储结构,是用数组来存储的。
    可以看到,i下标的数组元素,他的父节点是(i-1)/2,他的左右节点分别是i*2+1,i*2+2

    二、容量

    2.1初始容量11

    2.2扩展容量

        private void grow(int minCapacity) {
            int oldCapacity = queue.length;
            // Double size if small; else grow by 50%
            int newCapacity = oldCapacity + ((oldCapacity < 64) ? (oldCapacity + 2) : (oldCapacity >> 1));
            // overflow-conscious code
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
            queue = Arrays.copyOf(queue, newCapacity);
        }
    
    当容量不足的时候,会调用此方法,如果当前容量较小(小于64),则将容量增大一倍+2,如果当前容量较大,则容量增大一半

    三、插入

    插入元素会调用siftUp方法。
        private void siftUpComparable(int k, E x) {
            Comparable<? super E> key = (Comparable<? super E>) x;
            while (k > 0) {
                int parent = (k - 1) >>> 1;
                Object e = queue[parent];
                if (key.compareTo((E) e) >= 0)
                    break;
                queue[k] = e;
                k = parent;
            }
            queue[k] = key;
        }
    
    当优先队列不指定比较器的时候,插入元素,会调用siftUpComparable
    k表示元素将要插入的位置
    这个方法的意思是,在以k为子节点的子树插入元素x,并保持该子树的顺序。(把k看作这个子树的叶子节点)
    step1:得出父元素的下标
    strp2:计算出要插入元素的位置k。如果插入元素大于父元素,将父元素移动到k的位置,k移动到其父元素,并从第一步开始循环执行
    step3:在k的位置插入元素

    四、删除

        private void siftDownComparable(int k, E x) {
            Comparable<? super E> key = (Comparable<? super E>)x;
            int half = size >>> 1;        // loop while a non-leaf
            while (k < half) {
                int child = (k << 1) + 1; // assume left child is least
                Object c = queue[child];
                int right = child + 1;
                if (right < size &&
                    ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
                    c = queue[child = right];
                if (key.compareTo((E) c) <= 0)
                    break;
                queue[k] = c;
                k = child;
            }
            queue[k] = key;
        }
    
    删除会调用这个方法。删除都是将队尾的元素替换掉删除掉的位置
    k表示元素将要插入的位置
    这个方法的意思是,在k的子树插入元素x,并保持k位置子树的顺序(x是其子树的最小节点)。(把k看作这个子树的根节点)
    这里要注意,像这种二叉树结构,下标大于size<<2都是叶子节点,其他的节点都有子节点。所以注意到循环条件,如果k是叶子节点的下标,则直接替换,因为其已经没有子树了,那么肯定是以其为根节点的最小元素
    step1:算出k的左右节点的下标
    step2:如果k大于左右节点中的最小一个,则k与最小的节点互换位置,并循环step1
    step3:在k位置赋值x



    查看原文:http://blog.zswlib.com/2016/10/31/jdk%e6%ba%90%e7%a0%81%e5%88%86%e6%9e%90priorityqueue/

  • 相关阅读:
    Tomcat学习笔记(九)
    在Windows上编译最新的CURL,含有zlib,openssl
    【转】测试LibreOffice SDK 开发环境配置(Windows)
    [转]LibreOffice-SDK 开发实战:嵌入MFC-View 和 C# Winform
    C++内存分配及变长数组的动态分配
    C++ 取得系统当前时间
    C# Winform程序获取外网IP地址
    【转】让Chrome化身成为摸鱼神器,利用Chorme运行布卡漫画以及其他安卓APK应用教程
    tesseract-ocr 出现 错误 Please make sure the TESSDATA_PREFIX environment variable is set to the parent d irectory of your "tessdata" directory.解决方案
    使用adb 查询data/data下的数据库
  • 原文地址:https://www.cnblogs.com/wewill/p/6016272.html
Copyright © 2011-2022 走看看