二叉堆是特殊的完全二叉樹。
定義,符合一下兩點即爲二叉堆:
1.是個堆
2.是個完全二叉樹
因爲是完全二叉樹,所以一般用數組存儲。
在數組中,f是父節點下標,l是左節點下標,r是右節點下標,son是子節點下標(l或者r)。
因爲是完全二叉樹,所以已知任何節點都能推斷出它的關聯節點:
(下標從0開始)
f = (son-1)/2
r = 2*f +1
l = 2*f +2
r = l +1
堆最常用於topN問題的求解。
堆的建立:
堆的建立有兩種方式,一種是自底向上(bottom-top),一種是自頂向下(top-bottom)
自頂向上:
構建方法是,從堆頂節點開始,順序的添加節點進去,每次添加到堆的最後(完全二叉樹的最後一個節點後),調整節點順序(節點依次向父節點比較大小,並調整)使其符合堆的定義。直至所有節點添加完畢,堆也就構建完成。
這種方法一般不用於構建過程,時間複雜度O(n*logn),複雜度過高。常用於動態新增節點。
自底向上:
二叉樹的葉子節點數 = 二叉樹的非葉子節點數 + 1
根據堆的定義,葉子節點已經符合了堆的性質,那麼只需要從len/2-1(len爲節點個數)處開始調整,每次調整保證當前節點符合堆的性質,直至調整至根結點。此時堆就構建完成。
時間複雜度爲O(n),時間複雜度計算起來比較麻煩,此處省略。
舉個例子:
節點個數爲15,從15/2 -1 處,即下標爲6的節點開始調整,保證它大於它的子節點(不符合則和子節點交換即可)。再調整下標爲5的節點,依次類推,直到調整到下標爲0的節點(根節點)。即構建完成
堆排序相對很簡單:
1.建堆,採用自底向上建堆的方法即可。
2.將堆頂節點和堆的最後一個節點置換,堆長度減一,將置換後的堆頂節點進行下沉操作。
3.重複2操作,直至堆長度爲0.
堆排序時間複雜度爲O(n*logn) 但是常數係數較大,平均性能沒有快速排序好。但是優點是時間穩定,數據量相同時排序時間最好時間和最壞時間相差不大。