← 返回题目列表

什么是 Min-Max Heap?它如何同时支持取最小值和最大值?

困难 第 27 / 28 题 更新于 2026/07/30
Min-Max Heap双端优先队列

简化版

Min-Max Heap 是一种双端优先队列结构,既能快速取最小值,也能快速取最大值。

它按层交替维护最小层和最大层:最小层节点要小于其后代,最大层节点要大于其后代。根节点是最小值,最大值通常在根的两个孩子中。

它适合需要同时频繁删除最小值和最大值的场景,但实现复杂度高于普通堆。

详细版

普通小顶堆只能快速取最小值;普通大顶堆只能快速取最大值。

Min-Max Heap 用一个数组堆同时维护两端:

层级约束
偶数层Min 层,节点小于后代
奇数层Max 层,节点大于后代

因此:

  • 最小值在根节点;
  • 最大值在根的孩子中;
  • 插入和删除仍然是对数级。
level(index) = floor(log2(index + 1))

如果 level 是偶数,就按 Min 层规则调整;否则按 Max 层规则调整。

完整版教学

1. 为什么需要双端优先队列

普通优先队列只关注一端。

但有些场景需要同时支持:

  • 查看最小值;
  • 删除最小值;
  • 查看最大值;
  • 删除最大值。

例如实时数据窗口中既要剔除极大异常值,也要剔除极小异常值;或者调度系统既要拿最高优先级任务,也要清理最低优先级任务。

2. 用两个堆能不能做

可以用一个小顶堆和一个大顶堆,再配合懒删除。

这种方案工程上很常见:

结构作用
小顶堆取最小
大顶堆取最大
哈希表判断元素是否已经被另一边删除

Min-Max Heap 则试图用一个堆结构同时支持两端操作。

3. Min-Max Heap 的层级规则

Min-Max Heap 仍然是一棵完全二叉树,通常也用数组存储。

它的层级交替:

level 0: Min
level 1: Max
level 2: Min
level 3: Max

Min 层节点要小于它的所有后代,Max 层节点要大于它的所有后代。

它不是简单地左边小、右边大,而是按层维护最小约束和最大约束。

4. 为什么最小值在根,最大值在孩子

根节点位于 Min 层,并且要小于所有后代,所以根就是全局最小值。

根的两个孩子位于 Max 层。最大值不可能在更深的 Min 层绕过 Max 层祖先,因为 Max 层节点约束它大于后代。

因此全局最大值通常在根的两个孩子中,比较这两个孩子即可得到最大值。

如果元素数量小于 3,就按实际节点数处理边界。

5. 插入时如何调整

插入元素仍然先放到数组末尾。

然后判断它所在层:

  • 如果在 Min 层,但比父节点大,可能应该去 Max 层路径调整;
  • 如果在 Max 层,但比父节点小,可能应该去 Min 层路径调整;
  • 否则在当前层按祖父节点方向上浮。

调整时常会和祖父节点比较,因为同类型层级隔一层出现一次。

6. 删除最小和删除最大怎么做

删除最小值就是删除根,类似普通堆从最后拿元素填根,再按 Min 层规则下沉。

删除最大值时,先找根的较大孩子,再删除该孩子,之后按 Max 层规则下沉。

操作位置调整方向
删除最小根节点Min 层下沉
删除最大根的较大孩子Max 层下沉

复杂度都是 O(log n)

7. 和普通堆相比怎么评价

Min-Max Heap 的优势是一个结构同时支持双端优先队列。

缺点是实现更复杂,尤其是插入和下沉时要区分层级、父节点、祖父节点。

工程中,如果语言库没有现成实现,很多人会选择「双堆 + 懒删除」。

方案优点缺点
Min-Max Heap单结构、双端操作实现复杂
双堆懒删除借助标准库空间冗余、需清理过期

8. 常见误区与追问

  • 误区:Min-Max Heap 是一个小顶堆加一个大顶堆。 它是单个完全二叉树结构,按层交替维护约束。
  • 误区:最大值在数组最后。 最大值通常在根的两个孩子中,不是数组末尾。
  • 误区:Min-Max Heap 比双堆方案总是更好。 双堆方案更容易用标准库实现,工程上反而更常见。
  • 追问:为什么调整时常比较祖父节点? 因为同类层级隔一层出现,Min 层向上还是 Min 层要跨过父节点到祖父节点。
  • 追问:它适合什么场景? 适合频繁同时取最小和最大,并且愿意维护专门结构的双端优先队列场景。