#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
#include<string.h>
typedef int HPDataType;
//大堆
typedef struct Heap
{
HPDataType* a;
int size;
int capacity;
}HP;
void Swap(int* px, int* py);
void AdjustDown(int* a, int n, int parent);
void AdjustUp(int* a, int child);
//void HeapInit(HP* php);
void HeapInit(HP* php, HPDataType* a, int n);
void HeapDestroy(HP* php);
// 插入x,保持他继续是堆
void HeapPush(HP* php, HPDataType x);
// 删除堆顶数据,删除后保持他继续是堆
void HeapPop(HP* php);
// 获取堆顶的数据,也就是最值
HPDataType HeapTop(HP* php);
bool HeapEmpty(HP* php);
int HeapSize(HP* php);
void HeapPrint(HP* php);
#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
//建大堆
//向下调整算法
void AdjustDown(int* a, int n, int parent)
{
//父节点的左右子树都是大堆或者小堆可以直接建堆
int child = parent * 2 + 1;
while (child < n)
{
//先选出两个孩子中较大的那个
if (a[child] < a[child + 1] && child + 1 < n)
child++;
//孩子与父亲比较,孩子大就交换,孩子小就结束循环
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
//向上调整算法
//向堆中插入一个数据时可以用向上调整算法实现
void AdjustUp(int* a, int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
//孩子比父亲大,就交换,更新孩子父亲
if (a[child] > a[parent])
{
Swap(&a[child], &a[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
//排升序,建大堆,排降序,建小堆
void HeapSort(int* a, int n)
{
//n为个数
for (int i = (n - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(a, n, i);
}//建堆
//建堆后排序
int end = n - 1;
while (end > 0)
{
//堆顶和堆底不断交换,然后对除了堆底的其他部分进行重新建堆
//由于交换只会影响一条分支,所以建堆直接用向下调整即可
Swap(&a[0], &a[end]);
AdjustDown(a, end, 0);
end--;
}
}
void HeapInit(HP* php, HPDataType* a, int n)
{
assert(php);
php->a = (HP*)malloc(sizeof(HPDataType) * n);
if (php->a == NULL)
{
printf("malloc fail\n");
exit(-1);
}
memcpy(php->a, a, sizeof(HPDataType) * n);
for (int i = (n - 2) / 2; i >= 0; i--)
{
AdjustDown(php->a, n, i);
}
php->size = n;
php->capacity = n;
}
void HeapDestroy(HP* php)
{
assert(php);
free(php->a);
php->a = NULL;
php->size = php->capacity = 0;
}
void HeapPush(HP* php, HPDataType x)
{
assert(php);
if (php->size == php->capacity)
{
HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType) * php->capacity * 2);
if (php->a == NULL)
{
printf("realloc fail\n");
exit(-1);
}
php->capacity *= 2;
}
php->size++;
php->a[php->size - 1] = x;
AdjustUp(php->a, php->size - 1);
}
//删除堆顶元素
void HeapPop(HP* php)
{
assert(php);
assert(!HeapEmpty(php));
//先将对顶交换到最下面,然后重新向下调整
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;
}
HPDataType HeapTop(HP* php)
{
assert(php);
assert(!HeapEmpty(&php));
return php->a[0];
}
int HeapSize(HP* php)
{
assert(php);
return php->size;
}
void HeapPrint(HP* php)
{
for (int i = 0; i < php->size; i++)
printf("%d ", php->a[i]);
printf("\n");
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"Heap.h"
int main()
{
int a[] = { 27, 37, 28, 18, 19, 34, 65, 4, 2, 5, 7, 9, 3, 0, 25, 49, 15 };
HP hp;
HeapInit(&hp, a, sizeof(a) / sizeof(int));
HeapPrint(&hp);
HeapPush(&hp, 100);
HeapPrint(&hp);
HeapPop(&hp);
HeapPrint(&hp);
return 0;
}