堆及其操作

堆及其操作

  • 最大堆的创建
  • 最大堆的插入操作
  • 最大堆的删除操作
  • 建立最大堆

相关的代码如下:

#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版) 陈越主编

原文地址:https://www.cnblogs.com/Manual-Linux/p/11344403.html