最大堆是一种特殊的二叉树结构,它满足以下两个条件:
- 完全二叉树:树的每一层都被填满,除了最后一层,且所有的节点都尽可能向左对齐。
- 堆性质:每个节点的值都不小于其子节点的值(在最大堆中),即每个父节点的值都大于或等于其子节点的值。
最大堆通常用于实现优先队列,因为它能在 O(log n) 时间复杂度内支持插入和删除最大元素的操作。
#include <stdio.h>
#include <stdlib.h>
typedef int E; // 定义元素类型为整型
typedef struct MaxHeap {
E *arr; // 用数组来表示堆
int size; // 堆的当前大小
int capacity; // 堆的最大容量
} *Heap;
_Bool initHeap(Heap heap) { // 初始化堆
heap->size = 0; // 初始堆大小为0
heap->capacity = 10; // 初始堆的容量设为10
heap->arr = malloc(sizeof(E) * heap->capacity); // 为堆分配内存
return heap->arr != NULL; // 如果分配内存成功,返回true
}
_Bool insert(Heap heap, E element) { // 向堆中插入元素
if (heap->size == heap->capacity) return 0; // 如果堆已满,返回false
int index = ++heap->size; // 插入位置是当前堆大小+1(堆从1开始)
// 向上堆化:比较插入的元素和父节点,直到找到合适位置
while (index > 1 && element > heap->arr[index / 2]) {
heap->arr[index] = heap->arr[index / 2]; // 将父节点的值下移
index /= 2; // 上移到父节点位置
}
heap->arr[index] = element; // 将元素放置到合适位置
return 1; // 插入成功,返回true
}
void printHeap(Heap heap) { // 打印堆中的元素
for (int i = 1; i <= heap->size; ++i) // 堆的元素从1开始
printf("%d ", heap->arr[i]);
}
E delete(Heap heap) { // 删除堆中的最大元素(根节点)
E max = heap->arr[1], e = heap->arr[heap->size--]; // 获取最大元素,并将最后一个元素放到根节点
int index = 1;
// 向下堆化:从根节点开始,比较左右子节点,选择较大的子节点
while (index * 2 <= heap->size) {
int child = index * 2; // 左子节点
// 如果右子节点存在且大于左子节点,选择右子节点
if (child < heap->size && heap->arr[child] < heap->arr[child + 1])
child += 1;
// 如果当前元素大于或等于较大的子节点,堆化结束
if (e >= heap->arr[child]) break;
// 将较大的子节点上移
heap->arr[index] = heap->arr[child];
index = child; // 更新当前节点为子节点
}
heap->arr[index] = e; // 将最后的元素放置到合适位置
return max; // 返回最大元素
}
int main() {
struct MaxHeap heap; // 创建堆
initHeap(&heap); // 初始化堆
insert(&heap, 5); // 插入元素
insert(&heap, 2);
insert(&heap, 3);
insert(&heap, 7);
insert(&heap, 6);
printHeap(&heap); // 打印堆中的元素
printf("\n");
// 删除堆中的最大元素,并打印
for (int i = 0; i < 5; ++i) {
printf("%d ", delete(&heap));
}
}