最大堆和最小堆


參考:https://blog.csdn.net/guoweimelon/article/details/50904346

一、堆樹的定義

堆樹的定義如下:

(1)堆樹是一顆完全二叉樹;

(2)堆樹中某個節點的值總是不大於或不小於其孩子節點的值;

(3)堆樹中每個節點的子樹都是堆樹。

當父節點的鍵值總是大於或等於任何一個子節點的鍵值時為最大堆。 當父節點的鍵值總是小於或等於任何一個子節點的鍵值時為最小堆。如下圖所示,左邊為最大堆,右邊為最小堆。

二、堆樹的操作

以最大堆為例進行講解,最小堆同理。

原始數據為a[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7},采用順序存儲方式,對應的完全二叉樹如下圖所示:

(1)構造最大堆

在構造堆的基本思想就是:首先將每個葉子節點視為一個堆,再將每個葉子節點與其父節點一起構造成一個包含更多節點的對。

所以,在構造堆的時候,首先需要找到最后一個節點的父節點,從這個節點開始構造最大堆;直到該節點前面所有分支節點都處理完畢,這樣最大堆就構造完畢了。

假設樹的節點個數為n,以1為下標開始編號,直到n結束。對於節點i,其父節點為i/2;左孩子節點為i*2,右孩子節點為i*2+1。最后一個節點的下標為n,其父節點的下標為n/2。

 

如下圖所示,最后一個節點為7,其父節點為16,從16這個節點開始構造最大堆;構造完畢之后,轉移到下一個父節點2,直到所有父節點都構造完畢。

注意:上面構造最大堆的時候,從底而上,一層一層地不斷基於父節點構造最大堆,直至到達根節點完成整個最大堆的構造;

代碼如下:

//最大堆
//=======================================================================

#include <iostream>

using namespace std;

struct MaxHeap
{
    int *heap;  //數據元素的存放空間,下標從1開始存放元素,下標0存放臨時數據
    int HeapSize;  //數據元素的個數
    int MaxSize;  //存放數據元素空間的大小
};

//初始化最大堆
void MaxHeapint(MaxHeap &H)  
{
    for (int i = H.HeapSize / 2; i > 0; i--)
    {
        H.heap[0] = H.heap[i];
        int son = i * 2;
        while (son <= H.HeapSize)
        {
            if (son < H.HeapSize && H.heap[son] < H.heap[son + 1])
                son++;
            if (H.heap[son] < H.heap[0])
                break;
            else
            {
                H.heap[son / 2] = H.heap[son];
                son *= 2;
            }
        }
        H.heap[son / 2] = H.heap[0];
    }
}

//最大堆中插入節點
//思想:先在堆的最后添加一個節點,然后沿着堆樹上升。
void MaxHeapInsert(MaxHeap &H, int x)
{
    if (H.HeapSize == H.MaxSize)
        return;
    int i = ++H.HeapSize;
    while (i != 1 && x > H.heap[i / 2])
    {
        H.heap[i] = H.heap[i / 2];
        i = i / 2;
    }
    H.heap[i] = x;
}

//最大堆堆頂節點刪除
//思想:將堆樹的最后的節點提到根結點,然后刪除最大值,然后再把新的根節點放到合適的位置。
void MaxHeapDelete(MaxHeap &H , int &top)
{
    int x;
    if (H.HeapSize == 0)
        return;
    top = H.heap[1];
    H.heap[0] = H.heap[H.HeapSize--];
    int i = 1, son = i * 2;
    while (son <= H.HeapSize)
    {
        if (son < H.HeapSize && H.heap[son] < H.heap[son + 1])
            son++;
        if (H.heap[0] >= H.heap[son])
            break;
        H.heap[i] = H.heap[son];
        i = son;
        son = son * 2;
    }
    H.heap[i] = H.heap[0];
    return;
}

int main(void)
{
    int top;
    int &top_1 = top;
    MaxHeap H;
    cout << "請輸入數據的size: " << endl;
    cin >> H.HeapSize;
    H.heap = new int(H.HeapSize + 1);
    cout << "請按照完全二叉樹輸入數據:" << endl;
    for (int i = 0; i <= H.HeapSize; i++)
    {
        cin >> H.heap[i];  //我們這里默認H.heap[0]為臨時數據,設為0
    }
    
    MaxHeapint(H);  //將二叉樹轉換為最大堆
    MaxHeapInsert(H, 3);
    MaxHeapDelete(H, top);

    for (int i = 1; i <= H.HeapSize; i++)
    {
        cout << H.heap[i] << "  ";
    }
    cout << endl << top;
    system("pause");
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM