PriorityQueue理解


1、並非按FIFO進出


傳統的queue 是按先進先出的順序執行。而PriorityQueue是按優先級來絕對的

優先級低的先出queue

 

2、如何排序


 

PriorityQueue既然有優先級排序 那么如何排序的。

a. 放入隊列的元素實現了Comparable接口 按其自然順序排序 從小到大。

b. 初始化隊列時指明Comparator外部比較器。

PriorityQueue<String> queue1 = new PriorityQueue<>();
PriorityQueue<String> queue2 = new PriorityQueue<>(10);
PriorityQueue<String> queue3 = new PriorityQueue<>((a,b)->a.compareTo(b));

 

 

3、內部結構


 

內部使用數組存放元素:

transient Object[] queue;

數組默認容量11 (初始化時可以指定)  

 

動態擴容機制

容量<64 擴容為2*n+2,否則跟ArrayList一樣擴大為1.5n

(64是一個權衡的不大不小的值)

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);
    }

 

小根堆實現

小根堆:是一種完全二叉樹 且滿足父節點不大於任意一個左右子節點。(注意左右節點是沒有順序的)

所以小根堆的頂點必然是最小的 (如何要實現從大到小排序,指定的Comparator中取相反順序即可)

而完全二叉樹(所有節點滿足從左到右排列 不會垮節點)是可以用數組表示的。

PriorityQueue就是使用數組來實現的小根堆: 滿足每次取的數據都是最小的,但不滿足整體都是有序的

 

 

 

任意一個節點(數組中索引為n) 都可以知道其左右子節點和父節點在數組中的索引值:

父節點 : (n-1)/2

左子節點: 2n+1

右子節點:2n+2

  

關於節點的增刪

增:在完全二叉樹中依次創建一個新節點,再把新節點跟父節點依次比較,使其滿足最小堆要求

刪:刪除的節點 用二叉樹的最后一個節點先填充,再進行調整。

總是都是拿最有的節點處理,因為要滿足完全二叉樹。

具體細節網上例子很多 不再詳解。

 

4、非線程安全


PriorityQueue的線程安全版本:PriorityBlockingQueue,使用ReentrantLock加鎖保護

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM