以小堆为例,大堆就举一反三了。
堆的物理结构就是普通的数组,但是逻辑结构看成了一颗完全二叉树。
小堆,就是树的每一个父节点都小于他的孩子节点。如图中第一排的a与b。大堆,就是树的每一个父节点都大于他的孩子节点。如图中第二排的a与b。我们要实现的功能就是将一个数组排成符合要求的序列。

- typedef int HeapDataType;
-
- typedef struct Heap//小堆
- {
- HeapDataType* a;
- int size;
- int capacity;
- }HP;
- //初始化堆
- void HeapInit(HP* php)
- {
- assert(php);
- php->a = NULL;
- php->size = php->capacity = 0;
- }
- //Push数据
- void HeapPush(HP* php, HeapDataType x)
- {
- assert(php);
- if (php->size == php->capacity)
- {
- int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
- HeapDataType* temp = (HeapDataType*)realloc(php->a, sizeof(HeapDataType) * newcapacity);
- if (temp == NULL)
- {
- printf("realloc fail\n");
- exit(-1);
- }
- php->capacity = newcapacity;
- php->a = temp;
- }
- php->a[php->size++] = x;
- HeapAdjustUp(php->a, php->size-1);
- }
每一次删除堆顶元素,都会再次形成一个新的堆,新堆的堆顶元素就是数组a中次
小的值,再次删除,再形成新堆,堆顶就变成次次小的元素了。以此类推。
- //Pop数据
- void HeapPop(HP* php)
- {
- assert(php);
- assert(php->size > 0);
- Swap(&php->a[0], &php->a[php->size - 1]);
- php->size--;
- HeapAdjustDown(php->a, php->size, 0);
- }
- //获得堆顶数据
- HeapDataType HeapTop(HP* php)
- {
- assert(php);
- return php->a[0];
- }
- //获得堆的有效大小
- size_t HeapSize(HP* php)
- {
- return php->size;
- }
- //判断堆是否为空
- bool HeapEmpty(HP* php)
- {
- assert(php);
- return php->size == 0 ? 1 : 0;
- }
- //交换数据
- void Swap(HeapDataType* p1,HeapDataType* p2)
- {
- HeapDataType p3 = *p1;
- *p1 = *p2;
- *p2 = p3;
- }
- //向上调整数组形成堆
- void HeapAdjustUp(HeapDataType* a, int child)
- {
- int parent = (child - 1) / 2;
- while (child > 0)
- {
- if (a[parent] > a[child])
- {
- Swap(&a[parent], &a[child]);
- child = parent;
- parent = (child - 1) / 2;
- }
- else
- {
- break;
- }
- }
- }
- //向下调整数组形成堆
- void HeapAdjustDown(int* 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[parent] > a[child])
- {
- Swap(&a[parent], &a[child]);
- parent = child;
- child = parent * 2 + 1;
- }
- else
- {
- break;
- }
- }
- }
- //销毁堆
- void HeapDestory(HP* php)
- {
- assert(php);
- free(php->a);
- php->a = NULL;
- php->size = php->capacity = 0;
- }
- #pragma once
- #include "stdio.h"
- #include "stdlib.h"
- #include "string.h"
- #include "stdbool.h"
- #include "assert.h"
- #include "Heap.h"
-
- int main()
- {
- int a[] = { 4,6,2,1,5,8,2,9};
- HP hp;//创建堆
- HeapInit(&hp);//初始化堆
-
- //将数组a内数据Push到堆中
- for (int i = 0; i < sizeof(a) / sizeof(int); ++i)
- {
- HeapPush(&hp, a[i]);
- }
-
-
- int k = 3;
- while (k--)
- {
- printf("%d\n", HeapTop(&hp));
- HeapPop(&hp);//每一次删除堆顶元素,都会再次形成一个新的堆,新堆的堆顶元素就是数组a中次
- //小的值,再次删除,再形成新堆,堆顶就变成次次小的元素了。以此类推。
- //所以打出来的会是升序的
- }
-
- while (!HeapEmpty(&hp))
- {
- printf("%d\n", HeapTop(&hp));
- HeapPop(&hp);
- }
- printf("\n");
-
- return 0;
- }