大顶堆(Max Heap)是一种 二叉堆,用完全二叉树组织数据,并满足 堆序性:每个节点的值 不小于 其左右孩子的值。因此堆顶(根节点)始终是全局最大值。

本实现采用 数组存储 的定容二叉堆,通过 sift_up / sift_down 维护堆性质,支持 的插入与删除最大值。

特性push / pop · top · 空间 · 定容数组

完全二叉树与堆序性

堆在逻辑上是一棵 完全二叉树:除最后一层外每层均满,最后一层节点从左到右连续排列。大顶堆要求每个节点 不小于 其左右孩子;中序遍历 不保证 有序,但根始终是最大值。

数组表示

完全二叉树可压平为一维数组,根下标为 0:

关系公式
左孩子
右孩子
父节点

MaxHeapdata 数组存元素,size 为当前个数,capacity 为容量(满时 push 触发断言)。

代码实现

push 将新元素放到数组末尾后 上滤pop 将末尾元素移到堆顶后 下滤

void push(MaxHeap* heap, int value) {
    heap->data[heap->size++] = value;
    sift_up(heap, heap->size - 1);
}
 
int pop(MaxHeap* heap) {
    int t = top(heap);
    heap->data[0] = heap->data[--heap->size];
    sift_down(heap, 0);
    return t;
}
 
static void sift_up(MaxHeap* h, int i) {
    while (i > 0) {
        int p = parent(i);
        if (h->data[i] <= h->data[p]) break;
        swap(h, i, p);
        i = p;
    }
}
 
static void sift_down(MaxHeap* h, int i) {
    while (true) {
        int l = left(i), r = right(i), down = i;
        if (l < h->size && h->data[l] > h->data[down]) down = l;
        if (r < h->size && h->data[r] > h->data[down]) down = r;
        if (down == i) break;
        swap(h, i, down);
        i = down;
    }
}

连续 pop 会按 降序 输出所有元素,这也是 堆排序 的核心思路;一次性建堆见 线性时间构建堆

复杂度分析

设堆中有 个元素,树高

操作时间复杂度说明
push至多沿树高向上调整一次
pop至多沿树高向下调整一次
top直接读 data[0]
空间复杂度数组存储

与优先级队列

堆是 优先级队列(Priority Queue) 的经典实现:每次取出的都是当前优先级最高(此处为数值最大)的元素。C++ 的 std::priority_queue、Java 的 PriorityQueue 底层通常即为二叉堆。

本实现(定容数组堆)标准库优先级队列
底层结构数组 + 完全二叉树通常为二叉堆
扩容不支持(满则断言)动态扩容
取最值top / poptop / pop
插入pushpush

参考阅读