1. Heap.h
#ifndef __HEAP_H__
#define __HEAP_H__
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <windows.h>
typedef int HeapDateType;
typedef struct Heap
{
HeapDateType* _a;
size_t _size;
size_t _capacity;
}Heap;
void HeapInit(Heap* hp, HeapDateType* a, size_t n);
void HeapMake(Heap* hp);
void HeapPush(Heap* hp, HeapDateType x);
void HeapPop(Heap* hp);
size_t GetHeapSize(Heap* hp);
size_t HeapEmpty(Heap* hp);
HeapDateType HeapTop(Heap* hp);
void HeapSort(Heap* hp);
void HeapAdjustDown(Heap* hp, int root);
void HeapAdjustUp(Heap* hp, int child);
void HeapPrint(Heap *hp);
#endif __HEAP_H__
2. Heap.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Heap.h"
//初始化堆
void HeapInit(Heap* hp, HeapDateType* a, size_t n)
{
assert(hp);
hp->_a = (HeapDateType*)malloc(n*sizeof(HeapDateType));
memcpy(hp->_a, a, n*sizeof(HeapDateType));
hp->_size = n;
hp->_capacity = n;
}
//交换
void Swap(HeapDateType *x, HeapDateType *y)
{
*x ^= *y ^= *x ^= *y;
}
//调整大堆
void HeapAdjust(Heap* hp, int parent, int child)
{
int flag = 0; //调整标记
while (child < (int)hp->_size)
{
if (child + 1 < (int)hp->_size) //如果右孩子存在,比较左右孩子的数值大小
{
if (hp->_a[child] < hp->_a[child + 1])
{
child = child + 1; //child取数值大者
}
}
if (hp->_a[child]>hp->_a[parent]) //如果孩子节点数值大于双亲节点数值,进行交换
{
flag = 1;
Swap(&hp->_a[child], &hp->_a[parent]);
}
if (flag == 0) //没有调整,说明本身就是大顶堆,循环退出
{
break;
}
//进行一次调整后,此时可能导致其子树不满足堆的性质,继续向下调整子树直到满足堆的性质
parent = child;
child = parent * 2 + 1;
}
}
//自顶向下调整
void HeapAdjustDown(Heap* hp, int root)
{
assert(hp);
HeapAdjust(hp, root, root * 2 + 1);
}
//自底向上调整
void HeapAdjustUp(Heap* hp, int child)
{
assert(hp);
assert(child > 0 && child < (int)hp->_size);
while (child)
{
HeapDateType parent = (child - 1) / 2;
HeapAdjust(hp, parent, child);
child = parent;
}
}
//创建堆
void HeapMake(Heap* hp)
{
int parent = (int)(hp->_size - 2) / 2;
int child = 0;
for (; parent >= 0; parent--) //从最后一个非叶子节点开始调整,一直到根节点为止
{
child = parent * 2 + 1;
HeapAdjust(hp, parent, child);
}
}
//扩容
void CheckCapacity(Heap *hp)
{
assert(hp);
if (hp->_size >= hp->_capacity)
{
HeapDateType* ptr = (HeapDateType*)realloc(hp->_a, (hp->_capacity + 2)*sizeof(HeapDateType));
assert(ptr);
hp->_a = ptr;
hp->_capacity += 2;
}
}
//增加
void HeapPush(Heap* hp, HeapDateType x)
{
assert(hp);
CheckCapacity(hp);
hp->_a[hp->_size] = x; //插入到最后一个节点
hp->_size++;
HeapAdjustUp(hp, hp->_size - 1); //自底向上调整
}
//删除
void HeapPop(Heap* hp)
{
assert(hp);
if (hp->_size == 0)
{
return;
}
else if (hp->_size == 1)
{
hp->_size--;
}
else //至少有2个节点
{
hp->_a[0] = hp->_a[hp->_size - 1]; //将最后一个节点替换到第一个节点
hp->_size--;
HeapAdjustDown(hp, 0); //自顶向下调整
}
}
//节点个数
size_t GetHeapSize(Heap* hp)
{
assert(hp);
return hp->_size;
}
//判空
size_t HeapEmpty(Heap* hp)
{
assert(hp);
if (hp->_size)
{
return 0; //不为空
}
return 1; //为空
}
//获取堆顶元素
HeapDateType HeapTop(Heap* hp)
{
assert(hp);
if (hp->_size == 0)
{
return -1; //返回-1,代表该堆为空
}
return hp->_a[0];
}
//堆排序(建大顶堆->升序)
void HeapSort(Heap* hp)
{
assert(hp);
int sz = hp->_size;
while (hp->_size>1)
{
Swap(&hp->_a[0], &hp->_a[hp->_size - 1]); //将第一个节点和最后一个节点的数值交换
hp->_size--; //最后一个节点已为当前最大值,可不用考虑
HeapAdjustDown(hp, 0); //自顶向下调整
}
hp->_size = sz;
}
//输出
void HeapPrint(Heap *hp)
{
for (int i = 0; i < (int)hp->_size; i++)
{
printf("%d ", hp->_a[i]);
}
printf("\n");
}
3. test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Heap.h"
int main()
{
Heap hp;
HeapDateType a[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
size_t size = sizeof(a) / sizeof(HeapDateType);
HeapInit(&hp, a, size);
HeapMake(&hp);
printf("初始化堆:");
HeapPrint(&hp);
if (!HeapEmpty(&hp))
{
printf("节点数:%d\n", GetHeapSize(&hp));
}
printf("插入100:");
HeapPush(&hp, 100);
HeapPrint(&hp);
printf("删除:");
HeapPop(&hp);
HeapPrint(&hp);
printf("堆顶:%d\n", HeapTop(&hp));
printf("升序:");
HeapSort(&hp);
HeapPrint(&hp);
system("pause");
return 0;
}
Program execution result: