要說最大堆和最小堆,就得先知道最大樹和最小樹。
每個結點的值都大於(小於)或等於其子節點(如果有的話)值的樹,就叫最大(最小)樹。
最大堆(最小堆)是最大(最小)完全樹。
由於堆是完全二叉樹,所以可以用公式化描述,用一維陣列來有效的描述堆結構。
利用二叉樹的性質:
如果對一棵有n個結點的完全二叉樹的結點按層序編號(從第1層到第[log2n]向下取整+1層,每層從左到右),則對任一結點i(1≤i≤n),有:
(1)如果i=1,則結點i無雙親,是二叉樹的根;如果i>1,則其雙親是結點[i/2]向下取整。
(2)如果2i>n,則結點i為葉子結點,無左孩子;否則,其左孩子是結點2i。
(3)如果2i+1>n,則結點i無右孩子;否則,其右孩子是結點2i+1。
這樣就就可以將堆中結點移到它的父節點或者其中乙個子節點處。
堆中進行的操作主要是:插入,刪除,以及初始化。
下面只討論最大堆。
在最大堆中進行插入操作,例如在下圖所示的左邊的最大堆中進行插入,插入後結構應該是和右邊的圖一樣的。
插入時,現將新元素從新堆的父節點開始比較,也就是先從2所在結點開始比較,如果小於父節點的值,那麼就直接作為孩子結點插入,如果大於,那麼就要現將父節點下移,然後再和父節點的父節點比較,一直比較到根節點為止,所以插入過程,是從葉節點到根的一條路徑。
最大堆的刪除,從最大堆的刪除時,該元素從根部移出。刪除後,此時堆需要重新構造,以便於仍然為完全二叉樹。例如下圖:
先將根節點的值20取出後,為了結構仍然是二叉樹,所以直接將最後乙個結點,也就是儲存2的結點去掉,然後將2的值儲存下來,然後呢,就從根節點的兩個孩子開始比較,看看2 根的左右孩子,這三個元素中,誰最大,那麼根節點的值就是誰,然後就將2和空出來的結點的左右孩子(如果有的話)比較,確認子樹的根節點的值,這樣一步一步確認下去。
用陣列初始化堆,陣列元素顯示按照下面的順序,乙個乙個放在結點中
然後就從最後乙個父節點開始,就是第五個結點,10所在的位置啦,從那裡開始構造以該節點為根的最大堆。構造好後就移到下乙個結點,15所在結點,以此類推,一直到根節點。
下面是**:
檔案"maxheap.h"
#include using namespace std; template class maxheap ~maxheap() int get_size() const t get_max() heap[i]=x; cout
#include "maxheap.h" #include using namespace std; int main() ; cout<
在只是需要使用乙個優先佇列的時候,這種結構是十分有效率的,空間利用率也很高。但是並不適用於所有優先佇列的使用,尤其是需要合併兩個優先佇列或多個長度不相等的佇列的時候。
C 堆結構 陣列實現
要說最大堆和最小堆,就得先知道最大樹和最小樹。每個結點的值都大於 小於 或等於其子節點 如果有的話 值的樹,就叫最大 最小 樹。最大堆 最小堆 是最大 最小 完全樹。由於堆是完全二叉樹,所以可以用公式化描述,用一維陣列來有效的描述堆結構。利用二叉樹的性質 如果對一棵有n個結點的完全二叉樹的結點按層序...
c 小根堆陣列實現
主要功能 最小堆排序 大到小 void order 刪除首元素 type fetch root 插入元素 void insert item const type item void insert item faster const type item 快速版本 關鍵 source code file...
據結構與演算法 C 實現 二叉堆(陣列實現)
using system using system.collections namespace datastructure 堆中物件個數 public virtual int count 將成員陣列變成用1為基數表達的形式 public virtual object item int i regio...