🚗前言
本人是西安邮电大学的一个普通的 大学生,如果这篇文章对你有帮助的话请给我点个赞吧,球球了。
🎉堆的概念
直接上图
其实可以把堆看成一个完全二叉树,并且用数组实现。
左右孩子和双亲的关系就是这样的:
leftchild=parent*2+1;
rightchild=parent *2+2;
parent = (child-1)/2;
✈️堆的代码实现
heap.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
typedef int HPDataType;
typedef struct Heap
{
HPDataType* a;
size_t size;
size_t capacity;
}HP;
void Swap(HPDataType* pa, HPDataType* pb);
void HeapInit(HP* php);
void HpDestroy(HP* php);
void HeapPrint(HP* php);
// 插入x以后,保持他依旧是(大/小)堆
void HeapPush(HP* php, HPDataType x);
// 删除堆顶的数据。(最小/最大)
void HeapPop(HP* php);
bool HeapEmpty(HP* php);
size_t HpSize(HP* php);
HPDataType HeapTop(HP* php);
heap.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"heap.h"
void AdjustUp(HPDataType* a, size_t child)//看是大堆还是小堆,大堆父母比孩子大,小堆父母比孩子小
{
size_t parent = (child - 1) / 2;
while (child > 0)
{
if (a[child]>a[parent])
{
Swap(&a[parent], &a[child]);//要传地址
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
//看是大堆还是小堆,大堆父母比孩子大,小堆父母比孩子小
void AdjustDown(HPDataType* a, size_t size, size_t root)
{
size_t parent = root;
size_t child = parent * 2 + 1;
while (child<size)
{
if (child + 1 < size && a[child + 1] > a[child])
{
child++;
}
if (a[child] > a[parent])
{
Swap(&a[parent], &a[child]);//要传地址
parent = child;
child = parent*2+1;
}
else
{
break;
}
}
}
void Swap(HPDataType* pa, HPDataType* pb)
{
HPDataType tmp = *pa;
*pa = *pb;
*pb = tmp;
}
void HeapInit(HP* php)
{
assert(php);
php->a = NULL;
php->size = 0;
php->capacity = 0;
}
void HeapPrint(HP* php)
{
assert(php);
size_t i = 0;
for (i = 0; i<php->size; i++)
{
printf("%d ",php->a[i] );
}
printf("\n");
}
// 插入x以后,保持他依旧是(大/小)堆
void HeapPush(HP* php, HPDataType x)
{
assert(php);
if (php->capacity == php->size)
{
size_t newcapacity = php->capacity==0?4:(php->capacity*2);
HPDataType* tmp = (HPDataType*)realloc(php->a,sizeof(HPDataType)*newcapacity);//注意是realloc不是malloc
if (tmp == NULL)
{
printf("malloc failed\n");
exit(-1);
}
php->a = tmp;
php->capacity = newcapacity;
}
php->a[php->size] = x;
php->size++;
AdjustUp(php->a, php->size - 1);
}
void HpDestroy(HP* php)
{
assert(php);
free(php->a);
php->a = NULL;
php->size = 0;
php->capacity = 0;
}
// 删除堆顶的数据。(最小/最大)
void HeapPop(HP* php)
{
assert(php);
assert(php->size > 0);
Swap(&php->a[0], &php->a[php->size - 1]);
php->size--;
AdjustDown(php->a,php->size,0);
}
bool HeapEmpty(HP* php)
{
assert(php);
return php->size == 0;
}
size_t HpSize(HP* php)
{
assert(php);
return php->size;
}
HPDataType HeapTop(HP* php)
{
assert(php);
assert(php->size > 0);
return php->a[0];
}
test.c
void test1()
{
HP hp;
HeapInit(&hp);
HeapPush(&hp, 1);
HeapPush(&hp, 5);
HeapPush(&hp, 0);
HeapPush(&hp, 8);
HeapPush(&hp, 3);
HeapPush(&hp, 9);
HeapPush(&hp, 6);
HeapPush(&hp, 7);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
HpDestroy(&hp);
}
int main(void)
{
test1();
return 0;
}
🏍️堆排序
代码实现
这里用的是向上调整建大堆,然后进行堆排序。
void Swap(HPDataType* pa, HPDataType* pb)
{
HPDataType tmp = *pa;
*pa = *pb;
*pb = tmp;
}
void AdjustUp(HPDataType* a, size_t child)//看是大堆还是小堆,大堆父母比孩子大,小堆父母比孩子小
{
size_t parent = (child - 1) / 2;
while (child > 0)
{
if (a[child]>a[parent])
{
Swap(&a[parent], &a[child]);//要传地址
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
//看是大堆还是小堆,大堆父母比孩子大,小堆父母比孩子小
void AdjustDown(HPDataType* a, size_t size, size_t root)
{
size_t parent = root;
size_t child = parent * 2 + 1;
while (child<size)
{
if (child + 1 < size && a[child + 1] > a[child])
{
child++;
}
if (a[child] > a[parent])
{
Swap(&a[parent], &a[child]);//要传地址
parent = child;
child = parent*2+1;
}
else
{
break;
}
}
}
void HeapSort(int* a, int n)
{
int i = 1;
for (i = 1; i < n; i++)
{
AdjustUp(a, i);
}
int end = n - 1;
while (end>0)
{
Swap(&a[0],&a[end]);
AdjustDown(a, end, 0);
end--;
}
}
int main(void)
{
int a[10] = { 5,2,4,6,3,7,8,9,1,0 };
HeapSort(a, sizeof(a)/sizeof(a[0]));
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ",a[i]);
}
return 0;
}
🎉结语
既然都看到这里了就点个赞再走呗