堆的初始化,创建,插入,删除以及乱序输入的调整

注意:元素从下标为1开始存储,下标为0,存储最大值,用做哨兵;

#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXDATA = 1e6;    //哨兵最大值

typedef struct Node
{
    int  *Data;     //堆中存储元素数组
    int Size;       //当前元素个数
    int MaxSize;    //堆的最大容量
}*MaxHeap;

//初始化容量为maxSize的空的最大堆
MaxHeap CreatHeap(int maxSize)
{
    MaxHeap H = (MaxHeap)malloc(sizeof(Node));
    H->Data = (int *)malloc((maxSize + 1) * sizeof(int));

    //下标为零不存储有用值,存储最大值用于哨兵,方便以后操作;
    H->Data[0] = MAXDATA;
    H->MaxSize = maxSize;
    H->Size = 0;
    return H;
}

//判断最大堆是否已满
bool isFull(MaxHeap H)
{
    return H->Size == H->MaxSize;
}
//判断最大堆是否为空
bool isEmpty(MaxHeap H)
{
    return H->Size == 0;
}

//最大堆的插入(从下标为1开始,0为哨兵)
bool Insert(MaxHeap H, int X)
{
    if(isFull(H))
    {
        cout << "堆已满" <<endl;
        return false;
    }

    //pos为插入位置
    int pos = ++H->Size; //先将插入位置插到最后一个元素的下一个位置,再将Size自加
    //若父节点小于X,则进行交换,由于下标为零为最大值,一定在最大值时退出循环
    for(pos; H->Data[pos / 2] < X; pos /= 2)
    {
        H->Data[pos] = H->Data[pos / 2];
    }
    //此时pos为插入位置,进行插入
    H->Data[pos] = X;
    return true;
}

//最大堆删除;当然删除的是堆的根节点
bool DeleteMax(MaxHeap H)
{
    if(isEmpty(H))
    {
        cout << "堆为空" <<endl;
        return false;
    }
    int Parent, Child;
    int MaxElement = H->Data[1];    //根节点即下标为1为最大值
    int X = H->Data[H->Size--];   //取出最后一个元素并自减

    //找到最后一个元素要插入的位置Parent
    //Parent * 2为左儿子,有左儿子就进入;Parent = Child,往下走
    for(Parent = 1; Parent * 2 <= H->Size; Parent = Child)
    {
        Child = Parent * 2;     //左儿子
        //有右儿子并且左儿子小于右儿子,Child指向左右儿子中较大的一个
        if(Child != H->Size && H->Data[Child] < H->Data[Child + 1])
            Child++;

        //X仍然最大,直接退出;否则交换
        if(X > H->Data[Child]) break;
        else H->Data[Parent] = H->Data[Child];
    }
    //插入最后一个元素
    H->Data[Parent] = X;
    return MaxElement;      //返回要删除元素
}

//向下交换,使其成为最大堆,满足有序性;
//将以H->Data[p]为根的堆调整有序最大堆
void PerDown(MaxHeap H, int p)
{
    int Parent, Child;
    int X = H->Data[p];

    for(Parent = p; Parent * 2 <= H->Size; Parent = Child)
    {
        Child  = Parent * 2;
        if(Child != H->Size && H->Data[Child] < H->Data[Child + 1])
            Child++;
        if(X > H->Data[Child]) break;
        else H->Data[Parent] = H->Data[Child];
    }
    H->Data[Parent] = X;
}

//建造最大堆
void BuildHeap(MaxHeap H)
{
	//从第一个有儿子节点的父节点开始调整
    for(int i = H->Size / 2; i > 0; i--) PerDown(H, i);
}

int main()
{
    MaxHeap H;
    CreatHeap(10010);   //初始化
    //乱序输入
    for(int i = 1; i < 100; i++)
        cin >> H->Data[i],H->Size++;
    //调整为最大堆
    BuildHeap(H);
    //插入
    Insert(H, 98);
    //删除
    DeleteMax(H);

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值