堆及其操作
- 最大堆的创建
- 最大堆的插入操作
- 最大堆的删除操作
- 建立最大堆
相关的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXDATA 1000 //该值根据具体情况定义为大于堆中所有可能元素的值
#define ERROR -1 //错误标志 应根据具体情况定义为堆中不可能出现的元素值
//堆的C语言描述
struct HNode
{
int* Data; //存储元素的数组
int Size; //堆中当前元素的个数
int Capacity; //堆的最大容量
};
struct HNode* CreatHeap(int MaxSize)
{
struct HNode* H = (struct HNode*)malloc(sizeof(struct HNode));
H->Data = (int *)malloc((MaxSize + 1) * sizeof(int));
H->Size = 0;
H->Capacity = MaxSize;
H->Data[0] = MAXDATA; //定义哨兵为大于堆中所有可能元素的值
return H;
}
//作用:判断当前堆是否为空
bool IsFull(struct HNode* H)
{
return (H->Capacity == H->Size);
}
//作用:最大堆的插入操作
// 将元素X插入最大堆H,其中H->Data[0]已经定义为哨兵
bool Insert(struct HNode* H,int x)
{
int i;
if (IsFull(H))
{
printf("堆已满.
");
return false;
}
i = ++H->Size; //i指向插入后堆中最后一个元素的位置
for ( ; H->Data[i/2] < x ; i = i / 2)
{
H->Data[i] = H->Data[i / 2];
}
H->Data[i] = x;
return true;
}
//判断当前堆中元素是否为空
bool IsEmpty(struct HNode* H)
{
return (H->Size == 0);
}
//作用:从最大堆中取出键值最大的元素,并删除一个节点
int DeleteMax(struct HNode* H)
{
int Parent, Child;
int MaxItem;
int X;
if (IsEmpty(H))
{
printf("当前堆为空.
");
return false;
}
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
{
H->Data[Parent] = H->Data[Child];
}
}
H->Data[Parent] = X;
return true;
}
//作用:下滤 将H->Data[p]为根的子堆调整为最大堆
void PercDown(struct HNode* H,int p)
{
int Parent;
int Child;
int x;
x = H->Data[p]; //取出根节点存放的值
//退出循环的条件:当前的节点都被扫描了一遍
for (Parent = p; Parent * 2 <= H->Size; Parent = Child)
{
Child = Parent * 2;
if (H->Data[Child] < H->Data[Child + 1])
{
//当前指向了左右子节点较大值
Child = Child + 1;
}
if (x >= H->Data[Child])
{
//找到了合适的位置
break;
}
else
{
//交换父节点和较大子节点的位置
H->Data[Parent] = H->Data[Child];
}
}
H->Data[Parent] = x;
}
//作用:最大堆的建立
//这里假设所有H->Size个元素已经存在与H->Data[]中
void BuildHeap(struct HNode* H)
{
int i;
//从最后一个节点的父节点开始,到根节点
for (i = H->Size / 2;i > 0;i--)
{
PercDown(H,i);
}
}
void PrintHeap(struct HNode* H)
{
for (int i = 1;i <= H->Size;i++)
{
printf("%d.
",H->Data[i]);
}
}
int main()
{
struct HNode* Heap = CreatHeap(15);
int a[] = {18,25,44,58,10,31};
for (int i = 1;i <= sizeof(a) / sizeof(a[0]);i++)
{
Heap->Data[i] = a[i - 1];
Heap->Size++;
}
printf("构建堆:
");
BuildHeap(Heap);
PrintHeap(Heap);
printf("删除元素后:
");
DeleteMax(Heap);
PrintHeap(Heap);
printf("插入元素后:
");
Insert(Heap,58);
PrintHeap(Heap);
system("pause");
return 0;
}
参考资料:
1 https://www.jianshu.com/p/21bef3fc3030 最大堆(创建、删除、插入和堆排序)
2 《数据结构》(第2版) 陈越主编