Java之集合(六)PriorityQueue

  轉載請註明源出處:http://www.cnblogs.com/lighten/p/7299233.htmlhtml

1.前言

  本章介紹隊列中的PriorityQueue--優先隊列,顧名思義,這是一個能夠指定特定排序的隊列。有些違背隊列的先入先出,可是其是按照有序的出隊列,也是一個比較實用的類。數組

2.PriorityQueue

  PriorityQueue繼承自抽象父類AbstractQueue,其數據結構依舊保持簡單:數據結構

  一個數組隊列,一個大小,一個排序規則的比較器。若是比較器爲null的時候,就按照元素自身的compareTo方法進行比較排序。這個隊列和以前容器又在初始化的大小和擴容大小上不一致,其默認大小爲11,大小小於64的時候擴容後爲原來的3倍,大於64的時候,擴容後打下是原來的2倍。3d

  PriorityQueue的add(E)方法和offer(E)方法是同樣的。htm

  先判斷容量大小,再判斷是不是第一個,最後進行排序。blog

  這個排序看過去有些奇怪,怎麼有parent,而且下標是(k-1)>>>1呢?其實這裏的操做就反應了優先隊列的真正數據結構,其其實是一個二叉樹,將二叉樹存儲在數組之中而已。根節點就是數組的0位。下圖給出其具體結構:排序

  上圖就是隨手畫的一個二叉樹,下面是對應的二叉樹的數組中的位置。二叉樹存入數組的方式很簡單,就是從上到下,從左到右。PriorityQueue的是一個有特色的徹底二叉樹,且不容許出現null節點,其父節點都比葉子節點小,這個是堆排序中的小頂堆。若是按數組順序咱們能夠獲得以下結論:繼承

    左葉子節點=父節點下標*2+1隊列

    右葉子節點=父節點下標*2+2get

    父節點=(葉子節點-1)/2

  插入節點也就比較好處理了,和父節點比較,大於父節點的就不動,小於父節點的就上浮,這就是siftUp方法的做用了。順便一提,最小堆並不保證左右節點的大小關係,只關心父節點和子節點的關係。

  由上面的敘述,不難看出優先隊列若是不進行調整,是沒法保證優先順序的,子節點大小是無序的。因此每次出隊列的都是根元素,根元素確定是最小的。移除了一個元素後,樹的結構勢必會被破壞,因此每次的移除操做都會調整樹,保證其符合定義。

  siftDown就是用於作這樣的調整的,其具體實現以下:

  看代碼就能夠知道,其移除節點以後,是判斷了左右節點小的那個進行上浮的,然後循環上浮。

  移除任意一個位置的內容時,其是將最後一個元素取出來變成null了。而後調用siftDown,從新找到最後一個元素應該去的位置,其它元素填補移除位。通常而言這樣就應該足夠了,可是在某些狀況下還須要進行後面的元素與前面進行交換。就像代碼中所表現的同樣,最後一個元素正好填補的是移除的那個空缺,此種狀況下並不能說明該結構是正確的,形成這種現象的緣由就在於優先隊列並不保證左右的大小順序,看下圖就能很好理解問題所在,而且此種狀況須要進行siftUp(),當發生這種異常的狀況,纔會返回這個異常值,其它時候都是返回null.

 

3.示意圖

   移除任意位置的圖就再也不給出了,2小結結尾已經進行過說明,先進行一次siftDown,再進行一次siftUp。

 4.其它參考文章

  http://www.cnblogs.com/CarpenterLee/p/5488070.html

相關文章
相關標籤/搜索