最大堆的创建、插入、删除(完全二叉树)

一、最大堆的顺序存储

typedef struct HNode *Heap;//堆的类型定义
struct HNode{
    ElementType *Data;//存储元素的数组
    int Size;//堆中当前元素的个数 
    int  Capacity;//堆的最大容量 
}; 

typedef Heap MaxHeap;

二、最大堆的创建

Heap CreateHeap(int MaxSize)
{//创建容量为MaxSize的最大堆 
    MaxHeap H=(MaxHeap)malloc(sizeof(struct HNode));
    //第0个单位存放最大元素,所以元素一共有MaxSize+1个 
    H->Data =(ElementType *)malloc(sizeof(ElementType)*MaxSize+1);
    H->Data [0]=MaxData;//定义“哨兵” 为大于堆中的所有值 
    H->Size =0;
    H->Capacity =MaxSize;
    return H;
}

三、最大堆的插入

从新增的最后一个结点的父节点开始,用要插入的元素向下过滤上层结点

“哨兵”作用:跳出循环

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

bool Insert(MaxHeap H,ElementType X)
{
    int i;
    if(IsFull(H)){
        printf("堆满\n");
        return false;
    } 
    i=++H->Size ;//i指向插入后堆中的最后一个元素的位置
    for(;H->Data [i/2]<X;i/=2)
        H->Data [i]=H->Data [i/2];//上滤X,依次后移 
    H->Data [i]=X;//找到位置,将元素插入 
    return true; 
 } 

四、最大堆的删除

从根结点开始,用最大堆的最后一个元素向上过滤下层结点

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

//返回堆中最大元素值 
ElementType DeleteMax(MaxHeap H)
{
    //从最大堆H中取出键值最大的元素,并删除最后一个结点 
    int Parent,Child;
    ElementType MaxItem,X;
    if(IsEmpty(H)){
        printf("堆空\n");
        return ERROR;
    }
    MaxItem=H->Data [1];//取出根结点存放的最大值
    
    //用最大堆中最后一个元素从根结点开始向上过滤下层结点
    X=H->Data [H->Size --];//注意堆的规模要减小
    for(Parent=1;Parent*2<=H->Size ;Parent=Child){
        Child=Parent*2;
        if((Child!=H->Size )&&(H->Data[Child]<H->Data [Child+1]))
            Child++;//Child指向左右子树中较大者
        if(X>=H->Data [Child])break;//找到位置 
        else //下滤X
            H->Data [Parent]=H->Data [Child]; //元素上移 
    }
    H->Data [Parent]=X;//找到位置放入元素 
    return MaxItem;
}

五、最大堆的建立

步骤:

1.将N个元素依次存入二叉树中

  1. 调整各结点元素,满足最大堆的有序性

void PercDown(MaxHeap H,int p)
{
    //下滤:将H中以H->Data[p]为根的子堆调整为最大堆
    int Parent,Child;
    ElementType X;
    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++;//Child指向左右子树中较大者
        if(X>=H->Data [Child])break;//找到了合适的位置 
        else//下滤X 
            H->Data [Parent]=H->Data [Child];//元素上移
    }
    H->Data [Parent]=X;
 } 
 
void BuildHeap(MaxHeap H)
{
    //调整数组中的元素。使满足最大堆的有序性
    //这里假设H->Size个元素已经全部在H->Data里了 
    
    int i; 
    //从最后一个结点的父节点开始,到根结点1
    for(i=H->Size /2;i>0;i--)
        PercDown(H,i);
         
    return H;
}

六、完整代码

//最大堆——完全二叉树 

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

#define MaxData 1000 //大于堆中所有可能元素的值 
#define ERROR -1//错误标识,为最大堆中不可能取到的值 

typedef int ElementType;
/*------------最大堆的顺序存储--------------*/
typedef struct HNode *Heap;//堆的类型定义
struct HNode{
    ElementType *Data;//存储元素的数组
    int Size;//堆中当前元素的个数 
    int  Capacity;//堆的最大容量 
}; 

typedef Heap MaxHeap;
/*------------最大堆定义结束--------------*/


/*------------创建--------------*/
Heap CreateHeap(int MaxSize)
{//创建容量为MaxSize的最大堆 
    MaxHeap H=(MaxHeap)malloc(sizeof(struct HNode));
    //第0个单位存放最大元素,所以元素一共有MaxSize+1个 
    H->Data =(ElementType *)malloc(sizeof(ElementType)*MaxSize+1);
    H->Data [0]=MaxData;//定义“哨兵” 为大于堆中的所有值 
    H->Size =0;
    H->Capacity =MaxSize;
    return H;
}
/*------------创建结束--------------*/

/*------------插入--------------*/
/*从新增的最后一个结点的父节点开始,用要插入的元素向下过滤上层结点*/
//“哨兵”作用:跳出循环 
bool IsFull(MaxHeap H)
{
    return (H->Size ==H->Capacity);
} 

bool Insert(MaxHeap H,ElementType X)
{
    int i;
    if(IsFull(H)){
        printf("堆满\n");
        return false;
    } 
    i=++H->Size ;//i指向插入后堆中的最后一个元素的位置
    for(;H->Data [i/2]<X;i/=2)
        H->Data [i]=H->Data [i/2];//上滤X,依次后移 
    H->Data [i]=X;//找到位置,将元素插入 
    return true; 
 } 
/*------------插入结束--------------*/


/*------------删除--------------*/
/*从根结点开始,用最大堆的最后一个元素向上过滤下层结点*/
bool IsEmpty(MaxHeap H)
{
    return (H->Size ==0);
}

//返回堆中最大元素值 
ElementType DeleteMax(MaxHeap H)
{
    //从最大堆H中取出键值最大的元素,并删除最后一个结点 
    int Parent,Child;
    ElementType MaxItem,X;
    if(IsEmpty(H)){
        printf("堆空\n");
        return ERROR;
    }
    MaxItem=H->Data [1];//取出根结点存放的最大值
    
    //用最大堆中最后一个元素从根结点开始向上过滤下层结点
    X=H->Data [H->Size --];//注意堆的规模要减小
    for(Parent=1;Parent*2<=H->Size ;Parent=Child){
        Child=Parent*2;
        if((Child!=H->Size )&&(H->Data[Child]<H->Data [Child+1]))
            Child++;//Child指向左右子树中较大者
        if(X>=H->Data [Child])break;//找到位置 
        else //下滤X
            H->Data [Parent]=H->Data [Child]; //元素上移 
    }
    H->Data [Parent]=X;//找到位置放入元素 
    return MaxItem;
}

/*------------删除结束--------------*/


/*------------最大堆的建立--------------*/
/*
步骤:
1.将N个元素依次存入二叉树中
2.调整各结点元素,满足最大堆的有序性 
*/ 
void PercDown(MaxHeap H,int p)
{
    //下滤:将H中以H->Data[p]为根的子堆调整为最大堆
    int Parent,Child;
    ElementType X;
    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++;//Child指向左右子树中较大者
        if(X>=H->Data [Child])break;//找到了合适的位置 
        else//下滤X 
            H->Data [Parent]=H->Data [Child];//元素上移
    }
    H->Data [Parent]=X;
 } 
 
void BuildHeap(MaxHeap H)
{
    //调整数组中的元素。使满足最大堆的有序性
    //这里假设H->Size个元素已经全部在H->Data里了 
    
    int i; 
    //从最后一个结点的父节点开始,到根结点1
    for(i=H->Size /2;i>0;i--)
        PercDown(H,i);
         
    return H;
}


/*------------最大堆建立结束--------------*/

int main()
{
    MaxHeap H=CreateHeap(15);//创建一个容量为10的空堆
    
    //读取 
    printf("请输入堆的大小:");
    int size;
    scanf("%d",&size);
    H->Size=size;
    
    printf("请输入%d个元素:",size);
    int i=0;
    ElementType X;
    for(i=1;i<=size;i++){
        scanf("%d",&X);
        H->Data[i]=X;
    }
    //调整数组中的元素。使满足最大堆的有序性
    BuildHeap(H);
    //输出 
    printf("最大堆为:"); 
    for(i=1;i<=H->Size;i++)
        printf("%d ",H->Data [i]);
    printf("\n");

    //插入
    printf("请输入需要插入的元素:");
    scanf("%d",&X);
    Insert(H,X);
    printf("插入后的最大堆为:"); 
    for(i=1;i<=H->Size;i++)
        printf("%d ",H->Data [i]);
    printf("\n");
    
    //删除
    int max;
    max=DeleteMax(H);
    printf("删除元素:%d\n",max); 
    printf("删除后的最大堆为:"); 
    for(i=1;i<=H->Size;i++)
        printf("%d ",H->Data [i]);
    printf("\n");
    
     
    return 0;
}

七、运行

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值