#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<string.h>
typedef int DataType;
typedef int(*PFUNC)(int left, int right);//函数指针变量 有typedef PFUNC是类型 无typedef PFUNC是变量
typedef struct Heap
{
DataType* array;
int size;
int capacity;
//选择进行小堆还是大堆的实现
PFUNC Compare;
}Heap;
//左右孩子进行交换
void Swap(DataType* left, DataType* right)
{
DataType* temp = *left;
*left = *right;
*right = temp;
}
//判断是进行小堆还是大堆的实现
int Less(int left, int right)//选择小堆
{
return left < right;
}
int Greater(int left, int right)//选择大堆
{
return left > right;
}
//小堆的创建
void AdjustDown(Heap* hp, int parent)
{
int size = hp->size;
int* array = hp->array;
//child为左孩子
int child = parent * 2 + 1;
while (child < size)
{
//左右孩子进行比较,一定要较小的孩子
if (child+1 < size && hp->Compare(array[child + 1] , array[child]))//child+1(放前面)先判断有无右孩子,再进行左右孩子的比较
child = child + 1;
//再检验双亲与孩子的大小关系,不满足则交换
if (hp->Compare(array[child],array[parent]))
{
Swap(&array[child], &array[parent]);
//大的元素向下移动,可能导致子树不满足堆的特性
parent = child;
child = parent * 2 + 1;
}
else
return;
}
}
//堆顶的数据
DataType HeapTop(Heap* hp)
{
assert(hp);
return hp->array[0];
}
//堆的数据个数
int HeapSize(Heap* hp)
{
assert(hp);
return hp->size;
}
//堆的判断是否为空
int HeapEmpty(Heap* hp)
{
assert(hp);
return 0 == hp->size;
}
// 堆的构建
void HeapCreate(Heap* hp, DataType* a, int n,PFUNC Compare)
{
//开辟空间
hp->array = (DataType*)malloc(sizeof(DataType) * n);
if (hp->array == NULL)
{
assert(0);
return;
}
hp->capacity = n;
//将数组放入
memcpy(hp->array, a, sizeof(DataType) * n);
hp->size = n;
hp->Compare = Compare;
//判断是否为堆,不是将其转换为堆
//从倒数第一个非叶子节点开始调整(由下向上进行调整)
for (int root = ((n - 1) - 1) / 2; root >= 0; root--)//(n-1)为最后的节点,根据子节点=双亲节点*2+1得倒数第一个非叶子节点
{
AdjustDown(hp, root);
}
}
// 堆的销毁
void HeapDestory(Heap* hp)
{
assert(hp);
free(hp->array);
hp->array = NULL;
hp->capacity = 0;
hp->size = 0;
}
//堆尾向上调整
void HeapUp(Heap* hp, int child)
{
int* array = hp->array;
int parent = (child - 1) / 2;
while (child)
{
if (hp->Compare(array[child] , array[parent]))
{
Swap(&array[parent], &array[child]);
child = parent;
parent = (child - 1) / 2;
}
else
return;
}
}
//堆扩容
void CheckHeapCapacity(Heap* hp)
{
assert(hp);
if (hp->capacity == hp->size)
{
//创建两倍容量
int newCapacity = hp->capacity * 2;
DataType* temp = (DataType*)malloc(sizeof(DataType) * newCapacity);
if (temp == NULL)
{
assert(0);
return;
}
//将旧空间元素转移到新空间
memcpy(temp, hp->array, sizeof(DataType) * hp->capacity);
//释放旧空间
free(hp->array);
hp->array = temp;
hp->capacity = newCapacity;
}
}
// 堆的插入(尾部插入)
void HeapPush(Heap* hp, DataType x)
{
//先进行扩容
CheckHeapCapacity(hp);
hp->array[hp->size] = x;
hp->size++;
//将新插入元素向上调整
HeapUp(hp, hp->size-1);
}
// 堆的删除O(logN)
void HeapPop(Heap* hp)
{
if (HeapEmpty(hp))
{
return;
}
//堆中有元素,将堆顶与堆尾元素进行交换
Swap(&hp->array[0], &hp->array[hp->size - 1]);
//将堆中元素数减1
hp->size--;
//将堆顶元素向下调整,进行整理
AdjustDown(hp, 0);
}
void TestTopk()
{
int array[] = { 27,15,19,18,28,34,65,49,25,37 };
// int array[] = { 49,65,27,34,19,28,18,15,25,37 };
Heap hp;
HeapCreate(&hp, array, sizeof(array) / sizeof(array[0]),Greater);//创建大堆用Greater 创建小堆Less
HeapPop(&hp);
HeapDestory(&hp);
}
void main()
{
TestTopk();
}
数据结构:堆的实现
最新推荐文章于 2024-07-21 01:34:40 发布