当k1、k2、k3……kn的数据按照完全二叉树的方式存放在数组中,且这个完全二叉树满足某个节点的值总是不大于(或不小于)其父节点的值时,称该完全二叉树为堆。
我们通过实际存储结构可以看出,堆的存储和顺序表都是存在数组中的,所以他们的结构十分相似。
typedef struct Heap
{
int* a;
int size;
int capacity;
}HP;
void HeapInit(HP* hp)
{
assert(hp);
hp->capacity = hp->size = 0;
hp->a = NULL;
}
void Heap_pushBack(HP* hp, int x)
{
assert(hp);
if (hp->capacity == hp->size) {
int NewCapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
int* tmp = (int*)realloc(hp->a, sizeof(int) * NewCapacity);
if (tmp == NULL) {
perror("relloc fail");
exit(-1);
}
hp->a = tmp;
hp->capacity = NewCapacity;
}
hp->a[hp->size] = x;
hp->size++;
AdjustUp(hp, hp->size-1);
}
void AdjustUp(HP* hp, int child)
{
assert(hp);
int parent = (child - 1) / 2;
while (child > 0) {
if (hp->a[child] < hp->a[parent]) {
Swap(&hp->a[child], &hp->a[parent]);
child = parent;
parent = (child - 1) / 2;
}
else {
break;
}
}
}
要是要建大堆,修改交换条件即可。
if (hp->a[child] > hp->a[parent]) {
Swap(&hp->a[child], &hp->a[parent]);
child = parent;
parent = (child - 1) / 2;
}
bool HeapEmpty(HP* hp)
{
assert(hp);
return hp->size == 0;
}
但是删除堆顶数据后,我们又需要挪动数据,且其中堆的大小关系完全被破坏
1.交换堆顶和堆的最后一个数据,删除最后一个数据(也就是交换后的堆顶数据)。
2.再向下调整数据,恢复堆的顺序结构
void Heap_popBack(HP* hp)
{
assert(hp);
assert(!HeapEmpty(hp));
Swap(&hp->a[0], &hp->a[hp->size - 1]);
hp->size--;
AdjustDown(&hp->a, hp->size, 0);
}
void AdjustDown(HP* hp, int size, int parent)
{
assert(hp);
int minChild = parent * 2 + 1;
while (minChild < size) {
if(minChild + 1 < size &&
hp->a[minChild] > hp->a[minChild + 1])
minChild++;
if (hp->a[minChild] < hp->a[parent]) {
Swap(&hp->a[minChild], &hp->a[parent]);
parent = minChild;
minChild = parent * 2 + 1;
}
else
{
break;
}
}
}
要是要建大堆,修改交换条件即可。
if(minChild + 1 < size &&
hp->a[minChild] < hp->a[minChild + 1])
minChild++;
if (hp->a[minChild] > hp->a[parent]) {
Swap(&hp->a[minChild], &hp->a[parent]);
parent = minChild;
minChild = parent * 2 + 1;
}
int HeaptopK(HP* hp)
{
assert(!HeapEmpty(hp));
return hp->a[0];
}
int HeapSize(HP* hp)
{
assert(!HeapEmpty(hp));
return hp->size;
}
void HeapPrint(HP* hp)
{
assert(hp);
for (int i = 0; i < hp->size; i++)
{
printf("%d ", hp->a[i]);
}
printf("\n");
}
void HeapDestory(HP* hp)
{
assert(hp);
free(hp->a);
hp->capacity = hp->size = 0;
}
#pragma once
#include
#include
#include
#include
typedef struct Heap
{
int* a;
int size;
int capacity;
}HP;
void HeapInit(HP* hp);
void Heap_pushBack(HP* hp, int x);
void Heap_popBack(HP* hp);
void Swap(int* a, int* b);
int HeaptopK(HP* hp);
#include "Heap.h"
void HeapPrint(HP* hp)
{
assert(hp);
for (int i = 0; i < hp->size; i++)
{
printf("%d ", hp->a[i]);
}
printf("\n");
}
void HeapInit(HP* hp)
{
assert(hp);
hp->capacity = hp->size = 0;
hp->a = NULL;
}
void AdjustUp(HP* hp, int child)
{
assert(hp);
int parent = (child - 1) / 2;
while (child > 0) {
if (hp->a[child] < hp->a[parent]) {
Swap(&hp->a[child], &hp->a[parent]);
child = parent;
parent = (child - 1) / 2;
}
else {
break;
}
}
}
void Heap_pushBack(HP* hp, int x)
{
assert(hp);
if (hp->capacity == hp->size) {
int NewCapacity = hp->capacity == 0 ? 4 : hp->capacity * 2;
int* tmp = (int*)realloc(hp->a, sizeof(int) * NewCapacity);
if (tmp == NULL) {
perror("relloc fail");
exit(-1);
}
hp->a = tmp;
hp->capacity = NewCapacity;
}
hp->a[hp->size] = x;
hp->size++;
AdjustUp(hp, hp->size-1);
}
void AdjustDown(HP* hp, int size, int parent)
{
assert(hp);
int minChild = parent * 2 + 1;
while (minChild < size) {
if(minChild + 1 < size && hp->a[minChild] < hp->a[minChild + 1])
minChild++;
if (hp->a[minChild] > hp->a[parent]) {
Swap(&hp->a[minChild], &hp->a[parent]);
parent = minChild;
minChild = parent * 2 + 1;
}
else
{
break;
}
}
}
bool HeapEmpty(HP* hp)
{
assert(hp);
return hp->size == 0;
}
void Heap_popBack(HP* hp)
{
assert(hp);
assert(!HeapEmpty(hp));
Swap(&hp->a[0], &hp->a[hp->size - 1]);
hp->size--;
AdjustDown(&hp->a, hp->size, 0);
}
void Swap(int* a, int* b)
{
int* tmp = *a;
*a = *b;
*b = tmp;
}
int HeapSize(HP* hp)
{
assert(!HeapEmpty(hp));
return hp->size;
}
int HeaptopK(HP* hp)
{
assert(!HeapEmpty(hp));
return hp->a[0];
}
void HeapDestory(HP* hp)
{
assert(hp);
free(hp->a);
hp->capacity = hp->size = 0;
}
#include "Heap.h"
int main()
{
HP hp;
HeapInit(&hp);
Heap_pushBack(&hp, 7);
Heap_pushBack(&hp, 6);
Heap_pushBack(&hp, 20);
Heap_pushBack(&hp, 2);
Heap_pushBack(&hp, 5);
Heap_pushBack(&hp, 15);
Heap_pushBack(&hp, 13);
Heap_pushBack(&hp, 12);
Heap_pushBack(&hp, 0);
Heap_pushBack(&hp, 1);
int a = HeaptopK(&hp);
HeapPrint(&hp);
Heap_popBack(&hp);
HeapPrint(&hp);
int b = HeaptopK(&hp);
printf("%d %d \n", a, b);
HeapDestory(&hp);
return 0;
}