什么是堆 堆(heap),是一類特殊的數據結構的統(tǒng)稱。它通常被看作一棵樹的數組對象。在隊列中,調度程序反復提取隊列中的第一個作業(yè)并運行,因為實際情況中某些時間較短的任務卻可能需要等待很長時間才能開始執(zhí)行,或者某些不短小、但很重要的作業(yè),同樣應當擁有優(yōu)先權。而堆就是為了解決此類問題而設計的數據結構。 二叉堆是一種特殊的堆,二叉堆是完全二叉樹或者近似完全二叉樹,二叉堆滿足堆特性:父節(jié)點的鍵值總是保持固定的序關系于任何一個子節(jié)點的鍵值,且每個節(jié)點的左子樹和右子樹都是一個二叉堆。 當父節(jié)點的鍵值總是大于任何一個子節(jié)點的鍵值時為最大堆,當父節(jié)點的鍵值總是小于或等于任何一個子節(jié)點的鍵值時為最小堆。 為了更加形象,我們常用帶數字的圓圈和線條來表示二叉堆等,但其實都是用數組來表示的。如果根節(jié)點在數組中的位置是1,第n個位置的子節(jié)點則分別在2n和2n 1位置上。 如下圖所描的,第2個位置的子節(jié)點在4和5,第4個位置的子節(jié)點在8和9。所以我們獲得父節(jié)點和子節(jié)點的方式如下:
假定表示堆的數組為 最大堆除了根以外所有結點i都滿足: 最小堆除了根以外所有結點i都滿足: 一個堆中結點的高度是該結點到葉借點最長簡單路徑上邊的數目,如上圖所示編號為4的結點的高度為1,編號為2的結點的高度為2,樹的高度就是3。 包含n個元素的隊可以看作一顆完全二叉樹,那么該堆的高度是 通過MAX-HEAPIFY維護最大堆 程序中,不可能所有的堆都天生就是最大堆,為了更好的使用堆這一數據結構,我們可能要人為地構造最大堆。 如何將一個雜亂排序的堆重新構造成最大堆,它的主要思路是: 從上往下,將父節(jié)點與子節(jié)點以此比較。如果父節(jié)點最大則進行下一步循環(huán),如果子節(jié)點更大,則將子節(jié)點與父節(jié)點位置互換,并進行下一步循環(huán)。注意父節(jié)點要與兩個子節(jié)點都進行比較。 如上圖說描述的,這里從結點為2開始做運算。先去 因此可以給出偽代碼如下:
在以上這些步驟中,調整A[i]、A[l]、A[r]的關系的時間代價為 T(n)≤T(2n/3) Θ(1) 也就是: T(n)=O(lgn) 通過BUILD-MAX-HEAP構建最大堆 前面我們通過自頂向下的方式維護了一個最大堆,這里將通過自底向上的方式通過MAX-HEAPIFY將一個 回顧一下上面的圖示,其總共有9個結點,取小于或等于9/2的最大整數為4,從4 1,4 2,一直到n都是該樹的葉子結點,你發(fā)現(xiàn)了么?這對任意n都是成立的哦。 因此這里我們就要從4開始不斷的調用MAX-HEAPIFY(A,i)來構建最大堆。 為什么會有這一思路呢? 原因是既然我們知道了哪些結點是葉子結點,從最后一個非葉子結點(這里是4)開始,一次調用MAX-HEAPIFY函數,就會將該結點與葉子結點做相應的調整,這其實也就是一個遞歸的過程。 圖示已經這么清晰了,就直接上偽代碼咯。
通過HEAPSORT進行堆排序算法 所謂的堆排序算法,先通過前面的BUILD-MAX-HEAP將輸入數組 如何讓原來根的子結點仍然是最大堆呢,可以通過從堆中去掉結點n,而這可以通過減少 通過不斷重復這一過程,知道堆的大小從 上圖的演進方式主要有兩點: 1)將 2)不斷調用MAX-HEAPIFY(A,1)對剩余的整個堆進行重新構建 一直到最后堆已經不存在了。
優(yōu)先隊列 下一篇博文我們就會介紹大名鼎鼎的快排,快速排序啦,歡迎童鞋們預定哦~ 話說堆排序雖然性能上不及快速排序,但作為一個盡心盡力的數據結構而言,其可謂業(yè)界良心吶。它還為我們提供了傳說中的“優(yōu)先隊列”。 優(yōu)先隊列(priority queue)和堆一樣,堆有最大堆和最小堆,優(yōu)先隊列也有最大優(yōu)先隊列和最小優(yōu)先隊列。 優(yōu)先隊列是一種用來維護由一組元素構成的集合S的數據結構,其中每個元素都有一個相關的值,稱之為關鍵字(key)。 一個最大優(yōu)先隊列支持一下操作: 這里來舉一個最大優(yōu)先隊列的示例,我曾在關于“50% CPU 占有率”題目的內容擴展 這篇博文中簡單介紹過Windows的系統(tǒng)進程機制。 這里以圖片的形式簡單的貼出來如下: 在用堆實現(xiàn)優(yōu)先隊列時,需要在堆中的每個元素里存儲對應對象的句柄(handle)。句柄的準確含義依賴于具體的應用程序,可以是指針,也可以是整型數。 在堆的操作過程中,元素會改變其在數組中的位置,因此在具體實現(xiàn)中,在重新確定堆元素位置時,就自然而然地需要改變其在數組中的位置。 一、前面的
二、
三、 和上一個函數一樣,首先判斷a知否比原有的關鍵字更大。 然后就是老辦法了,不斷的將該結點與父結點做對比,如果父結點更小,那么就將他們進行對換。 相信有圖示會更加清楚,于是……再來一張圖。
在包含n個元素的堆上,HEAP-INCREASE-KEY的運行時間就是 四、
在包含n個元素的堆上,MAX-HEAP-INSERT的運行時間就是 總而言之,在一個包含n個元素的堆中,所有優(yōu)先隊列的操作時間都不會大于 來自:NoMasp柯于旺-CSDN博客 鏈接:http://blog.csdn.net/nomasp/article/details/46292633 |
|