← 中文资源

简体中文版本

二叉最小堆优先队列

实现无依赖的二叉最小堆,使用自定义比较器完成 O(log n) 入队与出队。

阅读英文原文

功能说明

MinHeap 是一个基于数组的二叉最小堆,支持任意类型元素和自定义比较器。push 把元素放到数组末尾后向上冒泡,pop 取出堆顶后用末尾元素下沉修复堆序,peek 以 O(1) 查看堆顶。它适合任务调度、合并有序流、Dijkstra 最短路和 Top-K 统计等需要反复取最小值的场景。

默认比较器按数值升序排列;传入返回负数的比较器即可定义“最小”的含义,例如按优先级和提交顺序排序的任务对象。from 静态方法可以批量构建堆。实现只使用私有字段,不依赖任何第三方库。

关键代码

入堆时不断与父节点比较,若当前元素更小则交换;出堆时把最后一个元素放到堆顶,再与较小的子节点交换直到恢复堆序。

push(value) {
  this.#items.push(value);
  this.#bubbleUp(this.#items.length - 1);
  return this;
}

pop() {
  if (this.#items.length === 0) return undefined;
  const root = this.#items[0];
  const last = this.#items.pop();
  if (this.#items.length > 0) {
    this.#items[0] = last;
    this.#sinkDown(0);
  }
  return root;
}

使用注意

比较器必须满足全序关系并保持稳定,否则堆序可能被破坏;默认比较器只适用于可直接相减的数值,字符串应传入 localeCompare 或自定义比较。堆中允许重复元素,peek 和 pop 在空堆上返回 undefined,因此不能区分“存储了 undefined”和“堆为空”。

from 会逐个插入元素,时间复杂度为 O(n log n),而不是线性建堆;对性能敏感的大批量数据可以改成从中间向前下沉。堆不是稳定排序结构,相同优先级的元素出队顺序由比较器决定,示例通过附加递增序号来保证先进先出。修改已入堆对象的排序字段会破坏堆序,需要重新入堆。

验证方式

示例把四个任务按不同优先级加入堆,出队顺序应为 charge-card、send-email、warm-cache、rotate-logs,其中同优先级的两个任务按 sequence 保持先后。随后用 MinHeap.from([5, 1, 4, 2, 3]) 逐个弹出,输出 1,2,3,4,5,验证基本堆序和批量构建。