🖊作者 : D. Star.
📘专栏 : 数据结构
😆今日分享 :开心的方法:1、专注地洗碗,心无旁骛;2、整理房屋,让它变整洁;3、让所有人都听到你在唱歌。
【堆】的基本功能
🔎头文件–声明
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
#define HeapDataType int
typedef struct Heap
{
HeapDataType* a;
int size;
int capacity;
}HP;
//初始化
void HPInit(HP* hp);
//摧毁
void HPDestory(HP* hp);
//插入
void HPPush(HP* hp,HeapDataType x);
//打印
void HPPrint(HP* hp);
//向上调整
void AdjustUp(HeapDataType* a, int child);
//删掉第一个
void HPPop(HP* hp);
//交换
void HPSwap(HeapDataType* a, HeapDataType* b);
//向下调整
void AdjustDown(HeapDataType* a, int size, int parent);
//取堆顶的元素
HeapDataType HPTop(HP* hp);
//取堆最大的k个元素
void HPTopK(HP* hp,int k);
//堆的个数
int HPSize(HP* hp);
//判空
bool HPEmpty(HP* hp);
//建堆算法
🔎基本功能实现:
🌼初始化:
//初始化
void HPInit(HP* hp)
{
assert(hp);
hp->a = NULL;
hp->capacity = hp->size = 0;
}
🌼摧毁:
//摧毁
void HPDestory(HP* hp)
{
assert(hp);
free(hp->a);
hp->a = NULL;
hp->capacity = hp->size = 0;
}
🌼插入:
//插入
void HPPush(HP* hp, HeapDataType x)
{
assert(hp);
//判断数组是否为满
if (hp->capacity == hp->size)
{
HeapDataType newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
//扩容
HeapDataType* tmp = (HeapDataType*)realloc(hp->a, sizeof(HeapDataType) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
hp->a = tmp;
hp->capacity = newcapacity;
}
//插入
hp->a[hp->size] = x;
hp->size++;
//大堆
AdjustUp(hp->a, hp->size - 1);
}
🌼打印
//打印
void HPPrint(HP* hp)
{
assert(hp);
for (int i = 0; i < hp->size; i++)
{
printf("%d ",hp->a[i]);
}
printf("\n");
}
🌼向上调整–大堆
//向上调整--大堆
void AdjustUp(HeapDataType* a ,int child)
{
int parent = (child - 1) / 2;
while (child > 0 && (a[child] > a[parent]))
{
HPSwap(&a[child],&a[parent]);
child = parent;
parent = (child - 1) / 2;
}
}
🌼向下调整–小堆
//向上调整--小堆
void SmallAdjustUp(HeapDataType* a, int child)
{
int parent = (child - 1) / 2;
while (child > 0 && (a[child] < a[parent]))
{
HPSwap(&a[child], &a[parent]);
child = parent;
parent = (child - 1) / 2;
}
}
🌼交换
//交换
void HPSwap(HeapDataType* a, HeapDataType* b)
{
assert(a);
HeapDataType tmp = *a;
*a = *b;
*b = tmp;
}
🌼删掉第一个元素
//删掉第一个
void HPPop(HP* hp)
{
assert(hp);
assert(hp->size > 0);
//第一个和最后一个交换数据
HPSwap(&hp->a[0], &hp->a[hp->size - 1]);
hp->size--;
//向下调整
AdjustDown(hp->a,hp->size,0);
}
🌼向下调整
//向下调整
void AdjustDown(HeapDataType* a, int size, int parent)
{
//先指向左子树,因为右子树不一定存在
int child = parent * 2 + 1;
while (child < size)
{
//确保child指向大的那一个
if (child+1 < size && a[child + 1] > a[child])
{
child++;
}
//1.孩子大于父亲,交换,继续向下调整
//2.孩子小于父亲,则结束
if (a[child] > a[parent])
{
HPSwap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
🌼取堆顶元素
//取堆顶的元素
HeapDataType HPTop(HP* hp)
{
assert(hp);
assert(hp->size > 0);
return hp->a[0];
}
🌼取出堆里面k个最大的元素
//取堆最大的k个元素
void HPTopK(HP* hp,int k)
{
assert(hp);
while (k--)
{
printf("%d ", HPTop(hp));
HPPop(hp);
}
}
🌼堆的个数
//堆的个数
int HPSize(HP* hp)
{
assert(hp);
return hp->size;
}
🌼判空
//判空
bool HPEmpty(HP* hp)
{
assert(hp);
return hp->size == 0;
}
🔎完整功能实现:
#define _CRT_SECURE_NO_WARNINGS
#include"heao.h"
//初始化
void HPInit(HP* hp)
{
assert(hp);
hp->a = NULL;
hp->capacity = hp->size = 0;
}
//摧毁
void HPDestory(HP* hp)
{
assert(hp);
free(hp->a);
hp->a = NULL;
hp->capacity = hp->size = 0;
}
//插入
void HPPush(HP* hp, HeapDataType x)
{
assert(hp);
//判断数组是否为满
if (hp->capacity == hp->size)
{
HeapDataType newcapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
//扩容
HeapDataType* tmp = (HeapDataType*)realloc(hp->a, sizeof(HeapDataType) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
hp->a = tmp;
hp->capacity = newcapacity;
}
//插入
hp->a[hp->size] = x;
hp->size++;
//大堆
AdjustUp(hp->a, hp->size - 1);
}
//打印
void HPPrint(HP* hp)
{
assert(hp);
for (int i = 0; i < hp->size; i++)
{
printf("%d ",hp->a[i]);
}
printf("\n");
}
//向上调整--大堆
void AdjustUp(HeapDataType* a ,int child)
{
int parent = (child - 1) / 2;
while (child > 0 && (a[child] > a[parent]))
{
HPSwap(&a[child],&a[parent]);
child = parent;
parent = (child - 1) / 2;
}
}
//向上调整--小堆
void SmallAdjustUp(HeapDataType* a, int child)
{
int parent = (child - 1) / 2;
while (child > 0 && (a[child] < a[parent]))
{
HPSwap(&a[child], &a[parent]);
child = parent;
parent = (child - 1) / 2;
}
}
//交换
void HPSwap(HeapDataType* a, HeapDataType* b)
{
assert(a);
HeapDataType tmp = *a;
*a = *b;
*b = tmp;
}
//删掉第一个
void HPPop(HP* hp)
{
assert(hp);
assert(hp->size > 0);
//第一个和最后一个交换数据
HPSwap(&hp->a[0], &hp->a[hp->size - 1]);
hp->size--;
//向下调整
AdjustDown(hp->a,hp->size,0);
}
//向下调整
void AdjustDown(HeapDataType* a, int size, int parent)
{
//先指向左子树,因为右子树不一定存在
int child = parent * 2 + 1;
while (child < size)
{
//确保child指向大的那一个
if (child+1 < size && a[child + 1] > a[child])
{
child++;
}
//1.孩子大于父亲,交换,继续向下调整
//2.孩子小于父亲,则结束
if (a[child] > a[parent])
{
HPSwap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
//取堆顶的元素
HeapDataType HPTop(HP* hp)
{
assert(hp);
assert(hp->size > 0);
return hp->a[0];
}
//取堆最大的k个元素
void HPTopK(HP* hp,int k)
{
assert(hp);
while (k--)
{
printf("%d ", HPTop(hp));
HPPop(hp);
}
}
//堆的个数
int HPSize(HP* hp)
{
assert(hp);
return hp->size;
}
//判空
bool HPEmpty(HP* hp)
{
assert(hp);
return hp->size == 0;
}
🔎测试代码:
#define _CRT_SECURE_NO_WARNINGS
#include"heao.h"
//HeapTest()
//{
// int a[] = { 12,23,34,56,14,12,2,1,70 };
// int sz = sizeof(a) / sizeof(a[0]);
// HP hp;
// HPInit(&hp);
// for (int i = 0; i < sz; i++)
// {
// HPPush(&hp, a[i]);
// }
//
// HPPrint(&hp);
//
// HPPop(&hp);
// HPPrint(&hp);
//
// HPDestory(&hp);
//}
test02()
{
int a[] = { 12,23,34,56,14,12,2,1,70 };
int sz = sizeof(a) / sizeof(a[0]);
HP hp;
HPInit(&hp);
for (int i = 0; i < sz; i++)
{
HPPush(&hp, a[i]);
}
HPPrint(&hp);
//HPPop(&hp);
//HPPop(&hp);
//HPPop(&hp);
//HPPop(&hp);
//HPPop(&hp);
//HPPop(&hp);
//HPPop(&hp);
//HPPop(&hp);
//HPPop(&hp);
//HPPrint(&hp);
printf("%d \n", HPSize(&hp));
if (HPEmpty(&hp))
{
printf("为空\n");
}
else printf("不为空\n");
//printf("%d ",HPTop(&hp));
//HPTopK(&hp, 5);
HPDestory(&hp);
}
int main()
{
//HeapTest();
test02();
system("pause");
return 0;
}
感谢家人的阅读,若有不准确的地方 欢迎在评论区指正!