天天看點

經典算法題每日演練——第九題 優先隊列

      前端時間玩小爬蟲的時候,我把url都是放在記憶體隊列裡面的,有時我們在抓取url的時候,通過lcs之類的相似度比較,發現某些url是很重要的,

需要後端解析伺服器優先處理,針對這種優先級比較大的url,普通的隊列還是苦逼的在做fifo操作,現在我們的需求就是優先級大的優先服務,要做

優先隊列,非堆莫屬。

一:堆結構

   1:性質

      堆是一種很松散的序結構樹,隻儲存了父節點和孩子節點的大小關系,并不規定左右孩子的大小,不像排序樹那樣嚴格,又因為堆是一種完全二叉

樹,設節點為i,則i/2是i的父節點,2i是i的左孩子,2i+1是i的右孩子,是以在實作方式上可以采用輕量級的數組。

經典算法題每日演練——第九題 優先隊列

2:用途

    如果大家玩過微軟的msmq的話,我們發現它其實也是一個優先隊列,還有剛才說的抓取url,不過很遺憾,為什麼.net類庫中沒有優先隊列,而java1.5

中就已經支援了。

3:實作

 <1>堆結構節點定義:

       我們在每個節點上定義一個level,表示該節點的優先級,也是建構堆時采取的依據。

<2> 入隊操作

      入隊操作時我們要注意幾個問題:

     ①:完全二叉樹的建構操作是“從上到下,從左到右”的形式,是以入隊的節點是放在數組的最後,也就是樹中葉子層的有序最右邊空位。

     ②:當節點插入到最後時,有可能破壞了堆的性質,此時我們要進行“上濾操作”,當然時間複雜度為o(lgn)。

經典算法題每日演練——第九題 優先隊列

當我将節點“20”插入到堆尾的時候,此時破壞了堆的性質,從圖中我們可以清楚的看到節點“20”的整個上濾過程,有意思吧,還有一點

就是:擷取插入節點的父親節點的算法是:parent=list.count/2-1。這也得益于完全二叉樹的特性。

<3> 出隊操作

       從圖中我們可以看出,優先級最大的節點會在一陣痙攣後上升到堆頂,出隊操作時,我們采取的方案是:彈出堆頂元素,然後将葉子層中

的最右子節點賦給堆頂,同樣這時也會可能存在破壞堆的性質,最後我們要被迫進行下濾操作。

經典算法題每日演練——第九題 優先隊列

我圖中可以看出:首先将堆頂20彈出,然後将7賦給堆頂,此時堆性質遭到破壞,最後我們清楚的看到節點7的下濾過程,從攤還分析的角度上

來說,下濾的層數不超過2-3層,是以整體上來說出隊的時間複雜度為一個常量o(1)。

最後我還擴充了一個彈出并下降節點優先級的方法,好吧,這個方法大家自己琢磨琢磨,很有意思的,實際應用中使用到了。

經典算法題每日演練——第九題 優先隊列

繼續閱讀