最大堆的建立插入刪除

堆(優先隊列)priority queue
特殊的隊列,取出元素的順序是依照元素的優先權(關鍵字)大小,而出元素進入隊列的先後順序
操作:查找最大值(最小值),刪除(最大值)

數組:
鏈表:
有序數組:
有序鏈表:

採用二叉搜索樹? NO

採用完全二叉樹 YES
堆的連個特性
結構性:用數組表示的完全二叉樹:
有序性:任一結點的關鍵字是其字樹所有結點的最大值(或最小值)
最大堆(MaxHeap)也稱大頂堆:最大值
最小堆(MinHeap)也稱“小頂堆”:最小值
從根節點到任意結點路徑上結點序列的有序性
操作:插入任意一個元素,刪除最 大值元素
最大堆的刪除:取出根節點(最大值)元素,同時刪除堆的一個結點

最大堆的建立:將已存在的N個元素按最大堆的要求存放在一個以爲數組中

#include <stdio.h>
#include <stdlib.h>
//最大堆

#define MaxData 1000        //哨兵,該值應該根據具體情況定義爲大於堆中所有可能元素的值

typedef int ElementType;

typedef struct HeapNode * MaxHeap;
struct HeapNode {
    int Capacity;            //堆的最大容量
    int Size;                //堆中當前元素個數
    ElementType *Data;    //用於存儲元素的數組
};

建一個空的最大堆:

//建立一個空的最大堆
MaxHeap InitHeap(int maxsize)
{
    MaxHeap H = (MaxHeap)malloc(sizeof(struct HeapNode));
    H->Data = (ElementType*)malloc(sizeof(struct HeapNode) * (maxsize + 1));        //堆中的元素是從下標爲1開始存儲的,但是爲了保證這個堆能存下maxsize個元素,所以要分配maxsize + 1個內存單元
    H->Capacity = maxsize;
    H->Size = 0;
    H->Data[0] = MaxData;            //將0下標的單元存儲哨兵
    for (int i = 1; i < maxsize + 1; i++)
        H->Data[i] = 0;
    return H;
}

判斷堆是否已滿或是否爲空:

int IsEmpty(MaxHeap H)
{
    return H->Size == 0;
}

//判斷堆是否已滿
int IsFull(MaxHeap H)
{
    return H->Size == H->Capacity;
}

插入一個元素:

//最大堆中插入一個元素
void Insert(MaxHeap H, ElementType item)
{
    int i;
    if (IsFull(H))
    {
        printf("The heap is full\n");
        return;
    }
    i = ++H->Size;        //i爲插入後堆中最後一個元素的位置
    for (; H->Data[i / 2] < item; i /= 2)
        H->Data[i] = H->Data[i / 2];        //循環退出時,父節點的數據已經大於item, item已經找到了正確的位置
    H->Data[i] = item;    //將item賦給正確的下標單元
}

刪除一個元素:

ElementType Delete(MaxHeap H)
{
    ElementType temp, Max;
    int parent = 1, child;
    if (IsEmpty(H))
    {
        printf("The heap is empty!\n");
        return 0;
    }
    Max = H->Data[1];            //現將最大值即根節點的值記錄下來
    temp = H->Data[H->Size--];        //用最後的結點元素暫時代替根節點的數據,然後將堆的數據大小減1

    //如果2 * parent > 0,那麼說明parent已經是根節點了
    for (; 2 * parent <= H->Size; parent = child)
    {
        child = 2 * parent;

        //如果Child != H->Size說明child不是最後一個結點,該parent結點還有右節點,
        //並且如果右節點的值大於左結點,那麼child++;
        if (child != H->Size && (H->Data[child + 1] < H->Data[child]))
            child++;        //child指向左右子節點的較大者
        if (temp > H->Data[child]) break;            //如果孩子結點已經小於temp了, 說明找到了合適的位置
        else
            H->Data[parent] = H->Data[child];
    }
    H->Data[parent] = temp;
    return Max;
}

最大堆的建立:

1.第一步,將N個元素按輸入順序存入二叉樹中,這一步需要求滿足完全二叉樹的結構特性,而不管其有序性

2.從最後一個右孩子的結點開始調整,做類似刪除元素時的下濾操作,逐個結點調整,直至根節點

//創建一個最大堆
MaxHeap CreateMaxHeap()
{
    int dt, i = 0, j;
    int parent, child;
    ElementType X;
    MaxHeap H = InitHeap(20);        //先創建一個空的最大堆,然後往裏面填充元素
    while (scanf_s("%d", &dt) != EOF)
    {
        H->Data[i + 1] = dt;
        i++;
        H->Size++;
    }
    for (j = i / 2; j >= 1; j--)        //從i / 2開始逐一向下過濾
    {
        //下面的操作和刪除元素是一模一樣的,只是不用將的元素個數減一
        X = H->Data[j];
        for (parent = j; 2 * parent <= H->Size; parent = child)
        {
            child = 2 * parent;
            if (child != H->Size && H->Data[child] < H->Data[child + 1])
                child++;
            if (H->Data[child] < X)
                break;
            else
                H->Data[parent] = H->Data[child];
        }
        H->Data[parent] = X;
    }
    return H;
}

打印堆中的元素:

//打印堆中元素
void printHeap(MaxHeap H)
{
    for (int i = 1; i <= H->Size; i++)
        printf("%d ", H->Data[i]);
    printf("\n");
}

先序建立樹:

void PreOrderCreateHeap(MaxHeap H, int index)
{
    int dt;
    scanf_s("%d", &dt);
    if (dt == 0)
    {
        return;
    }
    H->Size++;
    H->Data[index] = dt;
    printf("please enter the left child of %d :", dt);
    PreOrderCreateHeap(H, 2 * index);
    printf("please enter the right child of %d: ", dt);
    PreOrderCreateHeap(H, 2 * index + 1);
}

主函數:

int main()
{
    MaxHeap H = CreateMaxHeap();
    PreOrderCreateHeap(H, 1);
    printHeap(H);

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