數據結構 || 關於堆的那些事

  • 前面我們說二叉樹有兩種儲存方式

  • 1.鏈式存儲(之前已經實現過了)
    二叉樹的實現(C++版)

  • 2.順序存儲這便是我們要今天學習的堆了

  • 堆:理論上是按照完全二叉樹結構存儲的 ,物理上卻是以數組的方式存儲的

堆的概念及結構

  • 堆:如果有一個關鍵碼的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉樹的順序存儲方式存儲在一個一維數組中,並滿足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,則稱爲小堆(或大堆)。將根節點最大的堆叫做最大堆或大根堆,根節點最小的堆叫做最小堆或小根堆。

堆的性質

  • 堆中某個結點的值總是小於/不小於其父節點的值:
  • 堆是一顆完全二叉樹

在這裏插入圖片描述

  • 小根堆特點:根結點的結點值小於其左右孩子的結點值(左右孩子都在的情況下)

在這裏插入圖片描述

  • 大根堆特點:根結點的結點值大於左右孩子的結點值(左右孩子存在的情況下)

堆的向下調整

  • 當我們拿到一個數組的時,邏輯上將其看成一顆完全二叉樹,我們通過從第一個非葉子結點開始向下調整整個數組
    此處演示的是小根堆的向下調整
  • 大根堆調整成小根堆的過程圖示

在這裏插入圖片描述

  • 第一步:拿最後一個非葉子結點的值與(其父結點)左右孩子中較小的那個進行交換
  • 邏輯上的調整

在這裏插入圖片描述

  • 存儲結構上的調整(箭頭指出的是要調整的兩個結點)

在這裏插入圖片描述

  • 第二步:從上一個非葉子結點開始調整
  • 邏輯上的調整(第一步的調整結果及第二次調整的對象)

在這裏插入圖片描述

  • 存儲結構上的調整(上一次調整的結果和下一步要調整的兩個結點)

在這裏插入圖片描述

  • 第三步:對其前面的非葉子結點進行調整
  • 邏輯上的調整(第二步調整結果和第三步要調整的結點)
  • 可以看到堆中需要調整的結點已經是根結點了,但是調整並沒有完全結束,還需要繼續調整
    在這裏插入圖片描述
  • 存儲結構上的調整結果(上一次調整的結果和下一步要調整的兩個結點)

在這裏插入圖片描述

  • 第四步:繼續向下調整不符合堆性質的結點
  • 邏輯上的調整結果
  • 由圖可知根結點調整過後,整棵樹還是不符合堆的性質,需要繼續調整,而此處的調整目標變成了根結點中不符合堆性質的孩子結點,因此我們繼續進行調整
    在這裏插入圖片描述
  • 存儲結構上的調整
    在這裏插入圖片描述
  • 最終調整結果
  • 邏輯上的調整結果
    在這裏插入圖片描述
  • 存儲的調整結果
    在這裏插入圖片描述

堆的插入

此處我們演示向大根堆中插入數據

  • 未插入之前數據已經是有序的了(結點值符合大堆性質),而假如插入的值破壞了這種性質就需要進行向上的調整

  • 第一步:在數組尾部插入新的數據,並進行調整
    在這裏插入圖片描述

  • 第二步:判斷插入結點值與其父結點值的大小關係,若符合堆的性質,就結束調整.若不符合堆的性質就交換新結點值和其父結點值.再繼續往上調整直到滿足堆的性質才能結束調整

堆的刪除

刪除堆中元素是刪除堆頂的數據,將堆頂的數據根最後一個數據交換,然後刪除數組最後一個數據,再進行向下調
整算法。

  • 交換及刪除過程
  • 注意: 刪除的過程中只是改變了有效訪問數目,並沒有將空間釋放
    在這裏插入圖片描述
  • 向下調整

在這裏插入圖片描述

  • 調整到其符合堆的性質爲止
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章