数据结构-堆(最大堆)

最大堆

实质是一棵完全二叉树

每个根结点元素的值都比左右儿子的大

每次都是取出堆顶元素(可以说是优先队列)

代码

参考自浙大数据结构

#include <iostream>
#include <cstdio>
#include <algorithm>
#define ERROR -1
const int MAXDATA = 1<<30;
using namespace std;
typedef int ElementType;
typedef struct HeapStruct *MaxHeap;
struct HeapStruct
{
    ElementType *Elements; /*存储元素的数组*/
    int Size; /*当前堆元素个数*/
    int Capacity; /*堆的最大容量*/
};


/*建堆(申请需要的内存)*/
MaxHeap Creat(int MaxSize)
{
    /*创建容量为MaxSize的最大堆*/
    MaxHeap H = (MaxHeap)malloc(sizeof(struct HeapStruct));
    H->Elements = (ElementType*)malloc((MaxSize+1)*sizeof(ElementType));
    H->Size = 0;
    H->Capacity = MaxSize;
    H->Elements[0] = MAXDATA; /*定义哨兵为大于所有可能元素的值,以便后面更快操作*/
    return H;
}

bool IsFull(MaxHeap H)
{
    return H->Size == H->Capacity;
}
bool IsEmpty(MaxHeap H)
{
    return H->Size == 0;
}

void Insert(MaxHeap H,ElementType item)
{
    int i;
    if(IsFull(H))
    {
        printf("最大堆已满!\n");
        return;
    }
    i = ++H->Size; /*指向堆中最后一个元素的位置*/
    for( ; H->Elements[i/2] < item; i/=2)
    {
        H->Elements[i] = H->Elements[i/2]; /*下移小的item*/
    }
    H->Elements[i] = item; /*将item插入*/
}

ElementType Delete(MaxHeap H)
{
    if(IsEmpty(H))
    {
        printf("最大堆为空!\n");
        return ERROR;
    }
    int Parent,Child; /*parent指定最后一个元素temp放的位置*/
    ElementType MaxItem,temp;
    MaxItem = H->Elements[1]; /*取出根节点最大值*/
    temp = H->Elements[H->Size--]; /*用最大堆中最后一个元素从根结点开始向上过滤下层结点*/
    for(Parent = 1; Parent*2 <= H->Size; Parent = Child)
    {
        Child = Parent * 2;
        if((Child < H->Size)&&(H->Elements[Child] < H->Elements[Child+1]))
            Child++; /*Child指向左右结点较大者*/
        if(temp >= H->Elements[Child]) break;
        else /*移动temp到下一层:Parent = Child*/
            H->Elements[Parent] = H->Elements[Child];
    }
    H->Elements[Parent] = temp;
    return MaxItem;
}
void PushDown(MaxHeap H,int p)
{
    /*将H中以p为根结点的堆调整为最大堆*/
    int Parent,Child;
    ElementType X = H->Elements[p]; /*取根结点存放的值*/
    for(Parent = p; Parent * 2 <= H->Size; Parent = Child)
    {
        Child = Parent * 2;
        if((Child < H->Size) && (H->Elements[Child] < H->Elements[Child+1]))
            Child++; /*指向更大的结点*/

        if(X >= H->Elements[Child]) break;
        else H->Elements[Parent] = H->Elements[Child];/*调整*/
    }
    H->Elements[Parent] = X;
}

/*根据输入的数据构建好MaxHeap*/
void BuildHeap(MaxHeap H)
{
    /*
    与删除一个元素的调整策略相同
    从最后一个子堆根结点开始依次调整堆
    */
    for(int i = H->Size/2; i > 0; --i)
    {
        PushDown(H,i);
    }
}
int main()
{
    MaxHeap H = Creat(100);
    H->Size = 10;
    for(int i = 1; i <= 10; ++i)
    {
        H->Elements[i] = i;
    }
    BuildHeap(H);
    Insert(H,2021);
    Insert(H,1998);
    while(!IsEmpty(H))
    {
        printf("%d\n",Delete(H));
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leo Bliss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值