zoukankan      html  css  js  c++  java
  • PriorityBlockingQueue优先队列的二叉堆实现

    转载请注明原创地址http://www.cnblogs.com/dongxiao-yang/p/6293807.html

      

       java.util.concurrent.PriorityBlockingQueue内部用二叉堆实现了一个优先队列,所有插入的元素必须实现java.lang.Comparable接口。由于完全二叉树可以用数组来表示,所以队列内部元素存放在可变长度数组queue里。

     

    private transient Object[] queue; //用于存放元素的数组

     

    一 插入元素入队

     

        public boolean offer(E e) {
            if (e == null)
                throw new NullPointerException();
            final ReentrantLock lock = this.lock;
            lock.lock();
            int n, cap;
            Object[] array;
            while ((n = size) >= (cap = (array = queue).length))
                tryGrow(array, cap);
            try {
                Comparator<? super E> cmp = comparator;
                if (cmp == null)
                    siftUpComparable(n, e, array);
                else
                    siftUpUsingComparator(n, e, array, cmp);
                size = n + 1;
                notEmpty.signal();
            } finally {
                lock.unlock();
            }
            return true;
        } 


    //新元素堆内上浮实现

    private static <T> void siftUpComparable(int k, T x, Object[] array) { Comparable<? super T> key = (Comparable<? super T>) x; //尝试转化插入对象为Comparable实例 while (k > 0) { int parent = (k - 1) >>> 1; // 新元素x的数组下标为k,对应的父节点的下标为(k-1)/2 Object e = array[parent]; if (key.compareTo((T) e) >= 0) //如果子节点已经比父节点还要大,不需要再跟上层节点比较,新元素上浮结束 break; array[k] = e; //如果子节点已经比父节点小,父节点下沉,新元素上浮一次 k = parent; //新元素上浮后继续与新的父节点比较大小,直到k=0或者新的父节点小于新元素 } array[k] = key;//新元素在堆中插入正确的位置。 }

    一 弹出元素出队

        public E poll() {
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                return dequeue();
            } finally {
                lock.unlock();
            }
        }
    
        private E dequeue() {
            int n = size - 1;
            if (n < 0)
                return null;
            else {
                Object[] array = queue;
                E result = (E) array[0];
                E x = (E) array[n];
                array[n] = null;
                Comparator<? super E> cmp = comparator;
                if (cmp == null)
                    siftDownComparable(0, x, array, n);//堆顶的最小值被弹出了,堆顶变成了空节点,空节点开始下浮到合适位置后用数组最后子节点填充。
                else
                    siftDownUsingComparator(0, x, array, n, cmp);
                size = n;
                return result;
            }
        }
    //空元素堆内下沉实现
    private static <T> void siftDownComparable(int k, T x, Object[] array, int n) { if (n > 0) { Comparable<? super T> key = (Comparable<? super T>) x; int half = n >>> 1; // loop while a non-leaf half最后一个有子节点的父节点下标 while (k < half) { int child = (k << 1) + 1; // assume left child is least Object c = array[child]; int right = child + 1; if (right < n && ((Comparable<? super T>) c) .compareTo((T) array[right]) > 0) c = array[child = right]; //比较出左右子节点更小的那个子节点 if (key.compareTo((T) c) <= 0) //如果左右子节点的最小值大于数组末尾的值,那么数组末尾的值直接放到父节点,空节点下沉结束 break; array[k] = c; // 如果子节点最小值小于数据末尾的值,子节点上浮到父空节点 k = child; //空节点下滑到最小子节点的位置 } array[k] = key; // 最后空节点填充数组最后的值 } }

    参考资料:数据结构之优先队列--二叉堆(Java实现) 

  • 相关阅读:
    软件下载链接获取方法
    【转】Linux 查看端口占用情况
    [转]SpringBoot第十集:国际化与Webjars的应用(2020最新最易懂)
    【转】Vue生命周期理解(带图的哦)
    Visual Studio 2019&WebStorm&CMD 创建vue项目
    Qt-Button使用QSS变图片按钮
    Qt-滚动条QSS样式
    Qt-鼠标点击别处隐藏widget
    OSG-修改osg鼠标中轮放大缩小的操作键
    OSG-在使用单位的kit编译osgQOpenGL时提示“语法错误:"unit"的前面应有“:””
  • 原文地址:https://www.cnblogs.com/dongxiao-yang/p/6293807.html
Copyright © 2011-2022 走看看