最大堆、最小堆詳解

最大堆、最小堆詳解

Overview

最大堆和最小堆是二叉堆的兩種形式。二叉堆(binary heap)是一種特殊的堆,二叉堆是徹底二叉樹或者是近似徹底二叉樹。二叉堆知足堆特性:父節點老是保持固定的序關係於任何一個子節點的鍵值,且每一個節點的左子樹和右子樹都是一個二叉堆。java

1、二叉堆

二叉堆的表現形式:咱們能夠使用數組的索引來表示元素在二叉堆中的位置。web

在這裏插入圖片描述

從上圖中能夠得出:數組

  • 元素k的父節點所在數組中的位置爲[k/2]
  • 元素k的子節點所在數組中的位置爲2k和2k+1
  • 假設堆有n個節點,樹的高度爲h=floor(logn)

根據以上規則,咱們能夠使用二維數組來表示二叉堆。svg

2、最大堆、最小堆詳解

對於最大堆來講,最大元素位於根節點,那麼刪除操做就是交換根節點與堆的最後一個節點,而後將交換後的最後一個節點(交換前爲根節點,value爲最大值)移除並返回元素。此時新根節點須要下沉到適合的位置;當插入新元素的時候,將新元素添加至二叉堆的最後一個節點後,此時新節點須要根據value進行上浮操做,直到找到適合的位置。spa

最小堆和最大堆徹底相反,最小元素位於根節點,下沉、上浮操做和最大堆基本相同。3d

(以最大堆爲例)由上至下的下沉建堆操做

​ 當某一節點比其子節點要小時,根據最大堆的定義,咱們須要和其子節點中較大的子節點進行交換以從新建堆,直到該節點都大於其子節點爲止。code

在這裏插入圖片描述

source code:xml

private static void Sink(int k){
    while(2*k<N){
        int j = 2*k;
        if(H[j].CompareTo(H[j+1])<0)
            j++;
        if(H[k].CompareTo(H[j])>0)
            break;
        Swap(H,k,j);
        k=j;
    }
}

根據下沉(Sink)操做,能夠推出:移除並返回最大元素操做DelMax爲:blog

  1. 交換最後一個元素和根節點元素
  2. 對新根節點從上至下進行下沉動做,從新建堆
  3. 將最後一個元素置空

在這裏插入圖片描述

實現以下:索引

public static T DelMax()
{
    //根元素從1開始,0不存放值
    T max = pq[1];
    //將最後一個元素和根節點元素進行交換
    Swap(H, 1, N--);
    //對根節點從上至下從新建堆
    Sink(1);
    //將最後一個元素置爲空
    H[N + 1] = default(T);
    return max;
}

(以最大堆爲例)由下至上的上浮建堆操做

若是一個節點的值大於其父節點的值,那麼該節點須要上移,一直到知足該節點大於其兩個子節點,而小於其根節點爲止,從而達到使整個堆實現二叉堆的要求。

在這裏插入圖片描述

由上圖能夠看到,咱們只需將該元素k和其父元素k/2進行比較,若是比父元素大,則交換,而後迭代,一直到比父元素小爲止。

實現以下:

private static void Swim(int k)
{
    //若是元素比其父元素大,則交換
    while (k > 1 && H[k].CompareTo(H[k / 2]) > 0)
    {
        Swap(H, k, k / 2);
        k = k / 2;
    }
}

根據上浮操做,能夠得知,對於最大堆的插入操做變爲將該元素從下往上上浮,從新建堆操做:

  1. 將新元素添加至最大堆最後一個節點後
  2. 該元素進行從下至上的上浮動做
    在這裏插入圖片描述

實現以下:

public static void Insert(T s)
{
    //將元素添加到數組末尾
    H[++N] = s;
    //而後讓該元素從下至上重建堆
    Swim(N);
}

未完待續…