資料結構 - 堆(Heap)

Kindear_chen發表於2020-09-26

資料結構 - 堆(Heap)

1.堆的定義

堆的形式滿足完全二叉樹的定義:

  • i < ceil(n/2) ,則節點i為分支節點,否則為葉子節點
  • 葉子節點只可能在最大的兩層出現,而最大層次上的葉子節點都依次排列在該層最左側的位置上
  • 如果有度為1的節點,那麼只可能有一個,且該節點只有左孩子

根據堆定義的不同,分為大根堆和小根堆:

  • 大根堆每個節點的值都大於其子節點的值
  • 小根堆每個節點的值都小於其子節點的值

除此之外還有一個重要的內容:

  • 單節點也符合堆的特質

2.堆的初始化

堆的初始化可以可以分為如下幾個步驟(以初始化最大根堆為例):

  1. 首先初始化為完全二叉樹形式。
  2. 從最後一個具有孩子節點的節點進行調整,如果以該元素為根的子樹是最大根堆,則不進行操作,否則將該子樹調整為最大根堆(調整思路為不斷與子節點進行比較和交換,直至滿足最大根堆要求為止)。

  1. 陣列:[2,7,26,25,19,17,90,3],初始化為完全二叉樹形式。

  1. 調整最後一個具有孩子節點的節點[4],符合最大根堆要求,不進行操作。

  1. 調整節點[3],以滿足最大根堆要求,交換[3][7]

  1. 調整節點[2],以滿足最大根堆要求,交換[2][5]

  1. 調整節點[1],以滿足最大根堆要求,交換[1][3]後繼續交換[3][7],最終完成初始化,滿足最大根堆要求。

3.堆節點的插入和調整

如上圖所示,在如上所示圖中插入44

  1. 與父節點比較[4] 小於 [9],進行交換。

  1. 與父節點比較[2] 小於 [4],進行交換。

  1. 與父節點比較[1] 大於 [2],調整結束。

  1. 堆的初始化和插入的C++語言程式碼描述
/**
*@Author : Kindear
*@Intro  : DataStrcut C++ Code 以最大根堆為例
**/
#include <bits/stdc++.h>
#define ARR_SIZE 20
using namespace std;
typedef int ElementType;
void AdjustUp(ElementType A[],int k, int len) //該方法用於堆插入調整
{
    int Tmp = A[k]; //暫存k位置的數值
    int i = k/2; //父節點的下標
    while(i > 0 && A[i] < Tmp)
    {
        //如果該節點大於父節點,那麼就交換兩者的位置,滿足最大根堆的要求
        A[k] = A[i];
        k = i;
        i = k/2; //繼續向上尋找並調整,直至滿足最大根堆要求
    }
    A[k] = Tmp; //
}
void AdjustDown(ElementType A[],int k,int len) //該方法用於堆的初始化
{
    int Tmp = A[k];
    for(int i = 2*k; i <= len; i*=2) //向下篩選
    {
        if(i < len && A[i] < A[i+1]) i++;
        if(Tmp > A[i]) break;
        else
        {
            A[k] = A[i];
            k = i;
        }
    }
    A[k] = Tmp;
}
void BuildMaxHeap(ElementType A[],int len)
{
    for(int i= len/2 ; i > 0; i--)
    {
        AdjustDown(A,i,len);
    }
}
void PrintfElementArray(ElementType A[],int len)
{
    for(int i=1;i<=len;i++)
    {
        printf("%d%c",A[i],i==len?'\n':' ');
    }
}
int main()
{
    ElementType A[] = {0,2,7,26,25,19,17,90,3};
    ElementType B[ARR_SIZE];
    BuildMaxHeap(A,8);
    PrintfElementArray(A,8);
    for(int i=0;i<=8;i++)
    {
        B[i] = A[i];
    }
    B[9] = 44;//插入44
    AdjustUp(B,9,9);
    PrintfElementArray(B,9);
}

參考文件

[1] 資料結構堆視覺化:https://visualgo.net/zh/heap

相關文章