一、最大堆的顺序存储
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个元素依次存入二叉树中
调整各结点元素,满足最大堆的有序性
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;
}