堆的概念
堆实际上还是一棵二叉树,不过它还满足下列两点要求:
(1)堆是一棵完全二叉树。(关于完全二叉树的定义见:数据结构------二叉树的面试题)
(2)堆中元素满足:对任一棵树来说,它的根节点的值比它的左,右孩子都大或都小(注意:左右孩子之间没有明确的大小关系)。
根节点的值比它的左,右孩子元素都大的堆称为大(根)堆。
根节点的值比它的左,右孩子元素都小的堆称为小(根)堆。
堆的相关操作
在下文中将实现堆的一些相关操作:
(1)初始化(大/小)堆
(2)在堆中插入元素
(3)删除堆顶元素
(4)清空堆
(5)统计堆中的结点个数
(6)销毁堆
(7)根据堆来对一个数组进行排序
1. 堆的结构定义
因为堆是一棵完全二叉树。所以可以将堆用数组来进行表示。其中堆中根节点与左右孩子结点的下标满足如下关系(假设根节点的下标为i):左孩子节点下标:2*i+1,右孩子结点下标:2*i+2。所以根据下标可以很方便的对堆中的各节点进行操作。
数组最大容纳的元素个数也需要提前规定好。同时还需要定义一个size来表示堆中实际节点的格式。
根有大堆和小堆之分,所以在堆进行定义时,可以定义一个函数指针来确定是大堆还是小堆。
因此,结构定义如下:
typedef char HeapType;
#define MAXSIZE 100
typedef int (*Compare)(HeapType a,HeapType b);//定义一个函数指针用于表示是大堆还是小堆
typedef struct Heap
{
HeapType data[MAXSIZE];
size_t size;//堆中实际的节点个数
Compare cmp;//该参数用于判断是大堆还是小堆,在实际应用,由用户自己传参确定是创建大堆还是小堆
}Heap;
2. 堆的初始化
初始时,堆中元素应为0,且创建大堆还是小堆,需用户进行传参决定。
//堆的初始化:初始化时说明该堆是大堆还是小堆
void HeapInit(Heap* heap,Compare cmp)
{
if(heap == NULL)
{
//非法输入
return;
}
heap->size = 0;//初始时堆中节点个数为0
heap->cmp = cmp;//该堆是大堆还是小堆由用户传入的参数决定
return;
}
如果传参如下函数参数,表示是大堆:
int