深入理解Java PriorityQueue

小樓昨夜又西風發表於2019-03-17

底層程式碼實現原理參考連結:
https://www.cnblogs.com/CarpenterLee/p/5488070.html

PriorityQueue
PriorityQueue 是一個基於優先順序堆(???)的無界佇列,它的元素是按照自
然順序(natural order)(解釋:從小到大的順序)排序的。在建立的時候,我們可以給它提供一個負責給元素排序的比較器。PriorityQueue 不允許null 值,因為他們沒有自然順序,或者說他
們沒有任何的相關聯的比較器。最後,PriorityQueue 不是執行緒安全的,入隊和出
隊的時間複雜度是O(log(n))(解釋:因為是完全二叉樹,所以樹的高度是logn)。
堆樹的定義如下:
(1)堆樹是一顆完全二叉樹;
(2)堆樹中某個節點的值總是不大於或不小於其孩子節點的值;
(3)堆樹中每個節點的子樹都是堆樹。
在這裡插入圖片描述
1. 新增元素add()和offer()(解釋: PriorityQueue底層資料結構是最小堆,當然了我們只需要會用就行,沒必要管它底層是怎麼儲存的,原理如下也講的很詳細)
原理: 新增元素位於末尾,同時佇列長度加1,然後這個元素與它的父節點進行比較,如果比父節點小那麼就與父節點進行交換,然後再與交換後的位置的父節點進行比較,重複這個過程,直到該元素的值大於父節點結束這個過程。
區別: add(E e)和offer(E e)的語義相同,都是向優先佇列中插入元素,只是Queue 介面規定二者對插入失敗時的處理不同,前者在插入失敗時丟擲異常,後則則會返回false。對於PriorityQueue 這兩個方法其實沒什麼差
在這裡插入圖片描述
2. 尋找佇列的頭部元素element()和peek()頭部元素時間複雜度為1
element()和peek()的語義完全相同,都是獲取但不刪除隊首元素,也就是佇列中權值最小的那個元素,二者唯一的區別是當方法失敗時前者丟擲異常,後者返回null。根據小頂堆的性質,堆頂那個元素就是全域性最小的那個;由於堆用陣列表示,根據下標關係,0 下標處的那個元素既是堆頂元素。所以直接返回陣列0 下標處的那個元素即可。

3.刪除元素remove() 和poll()
區別:remove()和poll()方法的語義也完全相同,都是獲取並刪除隊首元素,區別是當方法
失敗時前者丟擲異常,後者返回null。由於刪除操作會改變佇列的結構,為維護小頂堆的
性質,需要進行必要的調整。
原理:該方法的作用是從k 指定的位置開始,將x 逐層向下與當前點的左右孩子中較小的
那個交換,直到x 小於或等於左右孩子中的任何一個為止
在這裡插入圖片描述

相關文章