krahets/hello-algo · error · Error
堆为空
Error message
堆为空
What it means
Thrown by pop() on a max-heap (MaxHeap) when the heap is empty. pop() swaps the root with the last leaf, removes the last element, then sifts the new root down to restore the heap property; calling it on an empty heap has no element to return, so the guard prevents an invalid swap/undefined return.
Source
Thrown at codes/javascript/chapter_heap/my_heap.js:85
/* 从节点 i 开始,从底至顶堆化 */
#siftUp(i) {
while (true) {
// 获取节点 i 的父节点
const p = this.#parent(i);
// 当“越过根节点”或“节点无须修复”时,结束堆化
if (p < 0 || this.#maxHeap[i] <= this.#maxHeap[p]) break;
// 交换两节点
this.#swap(i, p);
// 循环向上堆化
i = p;
}
}
/* 元素出堆 */
pop() {
// 判空处理
if (this.isEmpty()) throw new Error('堆为空');
// 交换根节点与最右叶节点(交换首元素与尾元素)
this.#swap(0, this.size() - 1);
// 删除节点
const val = this.#maxHeap.pop();
// 从顶至底堆化
this.#siftDown(0);
// 返回堆顶元素
return val;
}
/* 从节点 i 开始,从顶至底堆化 */
#siftDown(i) {
while (true) {
// 判断节点 i, l, r 中值最大的节点,记为 ma
const l = this.#left(i),
r = this.#right(i);
let ma = i;
if (l < this.size() && this.#maxHeap[l] > this.#maxHeap[ma]) ma = l;View on GitHub (pinned to 69932aed18)
Solutions
- Guard every pop: while (!heap.isEmpty()) { const x = heap.pop(); ... }.
- Check heap.size() > 0 before a single pop.
- Track enqueue/dequeue counts in the caller.
- If draining, break the loop on isEmpty() rather than catching the throw.
Example fix
// before
while (true) {
const x = heap.pop(); // throws when drained
}
// after
while (!heap.isEmpty()) {
const x = heap.pop();
} Defensive patterns
Strategy: validation
Validate before calling
function safePop(heap) {
if (!heap.isEmpty()) return heap.pop();
throw new Error('heap empty');
} Type guard
function heapHasElements(heap) {
return heap.size() > 0;
} Try / catch
try {
const x = heap.pop();
} catch (e) {
if (e instanceof Error && e.message === '堆为空') { /* drain complete */ } else throw e;
} Prevention
- Always drain with while (!heap.isEmpty()) heap.pop();.
- Track enqueue/dequeue counts in the caller.
- For priority queues, signal 'no task' via isEmpty() rather than catching the throw.
- Reset/validate heap state at the start of each processing round.
When it happens
Trigger: Calling pop() more times than elements were pushed; popping a freshly constructed heap; popping after the last element was already removed; popping in a loop without an emptiness guard.
Common situations: Drain loops (while(true) heap.pop()); priority-queue consumers pulling more tasks than were enqueued; using the heap as a sorting sink without checking size.
Related errors
AI-assisted analysis of krahets/hello-algo@69932aed18 (2026-08-13).
Data as JSON: /api/errors/678a0357ab86436f.
Report an issue: GitHub.