二叉堆使用完全二叉樹(其前n-1層必須被填滿,第n層也要從左到右順序填滿)來實現。
在二叉堆中,所有非終端結點的值均不大於(或不小於)其左右孩子的值。
若非終端結點的值均不大於其左右孩子結點的值,這樣的二叉堆叫做小根堆(下圖b),
小根堆根結點的值是該堆中所有結點的最小值;
同樣的,若非終端結點的值都不小於其左右孩子的值,這樣的堆叫做大根堆(下圖a),
大根堆根結點的值為改堆所有結點的最大值。利用堆的此性質,可以實現堆排序。
說明:小根堆和大根堆的實現沒有太大的區別,所以下面以大根堆為例。
堆一般使用陣列來構建,假設為陣列a,結點通常儲存在a[1],
這樣對於下標為k的結點a[k]來說,其左孩子的下標為2*k,右孩子的下標為2*k+1。
結點插入的位置應該是完全二叉樹的最後乙個位置(如下圖所示),
對於大根堆來講,需要滿足兩個性質:
(1)堆為完全二叉樹;(2)堆中每個父結點的值都不小於其左右子結點的值。
插入結點可能會破壞這兩條性質,所以在插入結點後需要對堆進行調整。
調整方法為:將插入的結點與其父結點比較,若大於其父結點的值,則交換兩者。
重複此操作,直至該結點不比其父結點大,或者該結點成為根結點。
可以通過插入結點到乙個已經存在的堆中,也可以通過不斷插入結點來構建乙個堆。
else break; //找到位置,退出迴圈
}}void insert(int val)
↓↓↓gettop:返回堆頂權值
//gettop
int gettop()
刪除堆頂元素(根結點)後,會得到左右兩棵子樹,此時將堆中最後乙個元素移到堆頂,
然後自上而下調整,將該結點與左右孩子結點比較,此時會有三種情況:
(1)結點的左右孩子均為空,此時調整結束;
(2)結點只有左孩子,將該結點與左比較。若結點小於其左孩子,則兩者交換,否則調整結束;
(3)結點左右孩子都非空,則將該結點與左右較小者比較,若小於則交換,否則調整結束;
重複此過程,直到該結點不小於其左右孩子結點,或者該結點為葉子結點。
//extract
//刪除堆頂元素,將末尾元素放到堆頂位置,再調整
void down(int p)
else break;
}}void extract()
//remove(p)
void up(int p)
else break; //找到位置,退出迴圈
}}void down(int p)
else break;
}}void remove(int p)
priority_queue實現了乙個大根堆。
支援 push(i),top(),pop()操作,不支援 remove 操作。
priority_queue*** 大根堆
priority_queue, greater> ***x 小根堆
——時間劃過風的軌跡,那個少年,還在等你。
二叉堆相關整理(大根堆小根堆)
二叉堆是一種支援插入 刪除 查詢最值的陣列結構。它其實是一棵滿足堆性質的完全二叉樹,樹上的每乙個節點都帶有乙個權值。層次序列儲存方式,直接用乙個陣列來儲存二叉堆。逐層從左到右為樹中的節點依次編號,把此編號作為節點在陣列中儲存的位置 下標 在這種儲存方式中,父節點編號等於子節點等於子節點編號除以2,左...
python實現二叉堆中的大頂堆 大根堆
堆 英語 heap 是電腦科學中一類特殊的資料結構的統稱。堆通常是乙個可以被看做一棵樹的陣列物件。堆總是滿足下列性質 將根節點最大的堆叫做最大堆或大根堆,根節點最小的堆叫做最小堆或小根堆。常見的堆有二叉堆 斐波那契堆等。他們的時間複雜度如下 0 先置為零,只要經過一次swap函式,就再次置為1 in...
(二叉)堆操作
堆操作 實驗目的 一 建堆 將陣列a 1.n 變成乙個最大堆。二 堆排序 將乙個堆中的元素按遞減排序輸出。三 用插入方法建堆 堆大小從1到n每次插入乙個元素到堆中,直到n個元素入堆。實驗原理 二叉 堆是乙個陣列,它可以被看成乙個近似的完全二叉樹。樹上的每乙個結點對應陣列中的乙個元素。除了最底層外,該...