【數據結構】堆{更新中}

 

堆的產生

堆的產生問題背景:如何在一堆動態變化的數中,以O(1)的複雜度獲取最值。

堆的目標:一個數組,支持刪除元素和添加元素,保證首元素永遠是數堆中的最值。

數組樹形化:比如給出數組  [7,9,8,1,10] , 一層一層依次從左到右加入節點,構造出如下圖所示的一顆樹,該種樹形稱爲完全二叉樹。

數組樹形化
完全二叉樹

對於數組 a,其所有元素的父子關係滿足\left\{\begin{matrix} a[i].l = a[2*i+1] \\ a[i].r = a[2*i+2] \end{matrix}\right. ,(2*i+1>=a.length,null)

完全二叉樹:每一層節點都是滿的,最底下一層葉子節點從左到右也是滿的。

完全二叉樹的數組化:可以用數組存儲,按層次從左到右遍歷樹節點。比如下圖。

完全二叉樹數組化
完全二叉樹層次遍歷數組化

堆的定義:

  • 邏輯上是一個完全二叉樹,支持刪除元素和添加元素,保證根元素永遠是數堆中的最值。其所有子樹也都是堆。
  • 物理存儲上,因爲完全二叉樹的節點可由數組存儲,所以是一個數組,所有節點的父/子節點在數組中的位置,可由公式計算得到。以 [7,9,8,1,10] 爲例,數組位置從 0 開始計。 9 的位置是 1 ,其父節點位置是  $\lfloor 1/2 \rfloor$ = 0 ,左子節點下標是 2*1+1 = 3 ,右子節點下標是 2*1+ 2= 4

堆示例: [7,9,8,1,10] 就不是堆,因爲 7 不是最值,且以 9 爲根的子樹,根也不是最值。 [10,9,8,1,7] 是堆,樹形化後如下圖所示:

滿足堆定義的數組

 

建堆

建堆的目標:以前面的數組   [7,9,8,1,10] 爲例,調整元素位置,使之對應的完全二叉樹,符合堆定義。

建堆的思路:把問題分解,從最小的樹開始調整。

建堆過程
建堆過程圖示
  • 先找到完全二叉樹中最低層的父節點。按父子關係公式逆運算,元素下標是  $\lfloor len/2 \rfloor$ ,就是 9。該樹只有最多三個節點,父節點與子節點中最大的節點互換位置,如果父節點最大就按兵不動。此時該元素( 9 )爲根的子樹滿足堆定義。
  • 繼續往前調整節點,此時元素下標是 $\lfloor len/2 \rfloor$ -1,就是 7,父子節點進行同樣的比較互換操作 (7,10,8) ,如果有更換(10與 7 互換了),那麼無法保證新的子節點值 7 是子樹的最大值,所以需要繼續將該子節點 7 和其子節點 1,9 進行同樣的比較互換操作,一直進行到比較時無需更換,或者沒有子節點爲止。
  • 繼續往前發現已經到數組首元素前面了,結束。
  • 前面對節點 7 一路向下的比較調整,稱爲向下調整。而前面從最低父節點 9 開始的建堆,我自稱爲向前建堆。

插入與刪除元素

插入和刪除的背景:

 

 

發佈了20 篇原創文章 · 獲贊 20 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章