解析從堆到優先隊列的實現

來源:互聯網
上載者:User

優先隊列,顧名思義,就是一種根據一定優先順序儲存和取出資料的隊列。它可以說是隊列和排序的完美結合體,不僅可以儲存資料,還可以將這些資料按照我們設定的規則進行排序。

先說說優先隊列的實現吧。有一點需要澄清,很多人一直以為Priority Queue就是一個Priority Heap,這種說法當然是片面的。既然優先隊列只是儲存資料和排序的結合,那麼根據我們學過的知識,可以列出以下的實現方法:無序數組、無序鏈表、有序數組、有序鏈表以及二叉尋找樹,當然還有堆。這些方法在實現中當然也有優先順序,下表就是一些方法的實現基本操作的時間效能對比:


圖1 一些優先隊列的實現方案的時間效能對比

從這張表裡我們可以按照時間複雜度這個優先順序來進行一次排序,當然,你會選用最後一種二叉尋找樹作為實現優先隊列的方案,但是實際上我們採用的是堆。堆,就是一種二叉樹,堆和二叉尋找樹是類似的,但是也有些許不同:從形狀來看,二叉尋找樹可以有不同的形狀,而堆只能是完全二叉樹;在時間效能上,二者並無明顯的區別。堆也是有序的,我們一般將其分為大頂堆和小頂堆。小頂堆,顧名思義,就是這個堆的子結點的值小於父結點的值;相反的,大頂堆就是堆的子結點的值都大於父結點的值。

在實現的時候,我們常常使用基於數組的堆,即堆中的元素儲存在一個數組中,而這個數組元素的儲存也是按照一定規律的:如果父結點的位置為n,那麼,其對應的左右子結點的位置分別是2n+1和2n+2。也就是說,我們在視覺上(如果用畫圖形象化表示堆的話)和本質上將堆打扮成兩種東西,這樣既便於理解,也利於實現,本質的實現是用數組是因為考慮到數組的一些效能。

堆有兩個很基本的操作:增加、刪除。先來說說增加元素,假設有下面這樣一個堆:

這時候,有一個元素1要添加進來,這時候應該怎麼辦呢?第一步,將元素添加到堆的最後一個位置:

第二步,將新加入的元素與其父結點的值進行比較,若新結點的值比其父結點的值要小(就像這個例子一樣),那麼,交換兩個結點的值,重複第二步,直到形成一個小頂堆:

這樣,一個新的小頂堆誕生了!

然後就是從堆中刪除一個元素了,假設在這個新的小頂堆中,我們打算刪除值為1的那個結點:

第一步,將這個1刪掉,假設其結點上當前沒有值:

第二步,比較該刪除結點(當前是最上面的那個)的兩個子結點,看誰的值小,交換其中較小值和這個空結點的值(假設是null),然後重複這一步,直到該空值到最小面一行:

第三步,就是將這個空的結點從視線中移除了,這樣,刪除的過程就告一段落了(好吧,這個堆又回到解放前了)!

知道了這些基本的原理,對資料量更大的增加和刪除也應該是觸類旁通了吧。

有人會質疑堆中除堆頂元素之外的其他元素的順序問題:

比如這裡為什麼4會放在5的右邊兄弟結點上,這明顯是受了二叉尋找樹的影響,因為堆對我們來說,一般只有堆頂元素有用,因此只要保證堆頂元素是最小的就行了(對小頂堆)。

下面,簡單介紹一下sun提供的PriorityQueue的一些基本的方法,以此來較為深入地理解優先隊列的實現機制:

1.下面是PriorityQueue的聲明的第一句話:

這句話表明:sun提供的優先隊列是基於優先堆實現的;

2.下面是聲明一個Object數組時的注釋:

由此可知,堆中的元素在數組中的儲存方案;並且隊列中的優先順序最小的元素總是儲存在queue[0]中,前提是該優先隊列不為空白。

下面是往PriorityQueue中上濾的方法:

這段代碼中,k代表當前加入元素的位置,即最後一個位置+1,x表示要添加的元素。首先得到父結點的值,然後將x的值和父結點的值進行比較,如果子結點的值大於父結點值,不作更改,否則交換兩者的值。這個方法主要用於添加元素的時候。與之相對應的有一個下濾方法siftDownComparable(),其功能是向下比較,用在刪除元素的實現中;

接下來就講添加元素的實現:

這裡可以看到用到了siftUp方法,其實,siftUp中分情況調用了 siftUpUsingComparator()、siftUpComparable()。這在剛才已經介紹了上濾的實現了。這裡的添加元素就是上濾的過程。

當然,我們在使用時,一般使用的方法是這三種:add、poll以及peek,add用以添加元素,其內部是用offer方法實現的,peek用來得到堆頂元素,但是不刪除,而poll在返回堆頂元素之後,將堆頂元素刪除。

以上只是對優先隊列的簡要介紹,作為一個應用比較廣泛的資料結構,優先隊列還有許許多多奇妙的地方,它們都等著你去發現。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.