头文件
#pragma once #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h> typedef int HPDataType; typedef struct Heap { HPDataType* a; int size; int capacity; }HP; //初始化 void HeapInit(HP* php); //销毁 void HeapDestroy(HP* php); //堆插入 void HeapPush(HP* php, HPDataType x); //规定删除堆顶(根节点) void HeapPop(HP* php); //找堆顶元素 HPDataType HeapTop(HP* php); //堆的元素个数 size_t HeapSize(HP* php); //是否是空 bool HeapEmpty(HP* php); //向上调整 void AdjustUp(HPDataType* a, int child); //向下调整 void AdjustDown(HPDataType* a, int size, int parent);
函数实现
初始化
void HeapInit(HP* php) { assert(php); php->a = NULL; php->capacity = 0; php->size = 0; }
销毁
void HeapDestroy(HP* php) { assert(php); free(php->a); php->a = NULL; php->capacity = php->size = 0; }
插入
//O(log N) void HeapPush(HP* php, HPDataType x) { assert(php); if (php->size == php->capacity) { int newCapacity = php->capacity == 0 ? 4 : php->capacity * 2; HPDataType* tmp = (HPDataType*)realloc(php->a, newCapacity * sizeof(HPDataType)); if (tmp == NULL) { perror("realloc fail"); exit(-1); } php->a = tmp; php->capacity = newCapacity; } php->a[php->size] = x; php->size++; AdjustUp(php->a, php->size - 1); }
向上调整
//小堆 void AdjustUp(HPDataType* a, int child) { int parent = (child - 1) / 2; while (child>0) { if (a[child] < a[parent]) { Swap(&a[child], &a[parent]); child = parent; parent = (parent - 1) / 2; } else { break; } } }
交换两个元素
void Swap(HPDataType* p1, HPDataType* p2) { HPDataType tmp = *p1; *p1 = *p2; *p2 = tmp; }
向下调整
//小堆 void AdjustDown(HPDataType* a, int size, int parent) { int child = parent * 2 + 1; while (child<size) { //假设左孩子小,如果假设错了,就更新一下 if (child+1<size&&a[child + 1] < a[child]) { child++; } if (a[child] < a[parent]) { Swap(&a[child], &a[parent]); parent = child; child = parent * 2 + 1; } else { break; } } }
删除(默认删堆顶元素)
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); }
找堆顶元素
HPDataType HeapTop(HP* php) { assert(php); assert(php->size>0); return php->a[0]; }
堆的大小
size_t HeapSize(HP* php) { assert(php); return php->size; }
是否为空
bool HeapEmpty(HP* php) { assert(php); return php->size == 0; }
注意:上面所建的堆是小堆,若需要建大堆,只需修改向上和向下调整的函数。