{"record":{"id":"6929d017cc45f10f","repo":"krahets/hello-algo","slug":"error-6929d0","errorCode":null,"errorMessage":"堆積為空","messagePattern":"堆積為空","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"zh-hant/codes/javascript/chapter_heap/my_heap.js","lineNumber":85,"sourceCode":"\n    /* 從節點 i 開始，從底至頂堆積化 */\n    #siftUp(i) {\n        while (true) {\n            // 獲取節點 i 的父節點\n            const p = this.#parent(i);\n            // 當“越過根節點”或“節點無須修復”時，結束堆積化\n            if (p < 0 || this.#maxHeap[i] <= this.#maxHeap[p]) break;\n            // 交換兩節點\n            this.#swap(i, p);\n            // 迴圈向上堆積化\n            i = p;\n        }\n    }\n\n    /* 元素出堆積 */\n    pop() {\n        // 判空處理\n        if (this.isEmpty()) throw new Error('堆積為空');\n        // 交換根節點與最右葉節點（交換首元素與尾元素）\n        this.#swap(0, this.size() - 1);\n        // 刪除節點\n        const val = this.#maxHeap.pop();\n        // 從頂至底堆積化\n        this.#siftDown(0);\n        // 返回堆積頂元素\n        return val;\n    }\n\n    /* 從節點 i 開始，從頂至底堆積化 */\n    #siftDown(i) {\n        while (true) {\n            // 判斷節點 i, l, r 中值最大的節點，記為 ma\n            const l = this.#left(i),\n                r = this.#right(i);\n            let ma = i;\n            if (l < this.size() && this.#maxHeap[l] > this.#maxHeap[ma]) ma = l;","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/zh-hant/codes/javascript/chapter_heap/my_heap.js#L67-L103","documentation":"Thrown by MaxHeap.pop() (message: '堆積為空' = 'heap is empty') when isEmpty() is true. pop() swaps the root with the last leaf, removes it, then sifts down; without the guard it would return undefined and corrupt heap ordering.","triggerScenarios":"Calling pop() on a heap that has no elements, or calling pop() more times than elements were pushed.","commonSituations":"Draining a heap/priority queue in a loop without a termination check; heap-sort on an already-empty collection; underflow from concurrent consumers.","solutions":["Check heap.isEmpty() before calling pop().","If consuming in a loop, use while (!heap.isEmpty()) as the loop condition.","Track element count externally if the heap is shared across producers/consumers."],"exampleFix":"// before\nconst val = heap.pop(); // throws '堆積為空' if empty\n\n// after\nwhile (!heap.isEmpty()) {\n    const val = heap.pop();\n}","handlingStrategy":"validation","validationCode":"if (!heap.isEmpty()) {\n    const val = heap.pop();\n}","typeGuard":null,"tryCatchPattern":"try {\n    const val = heap.pop();\n} catch (e) {\n    if (e.message === '堆積為空') {\n        // heap is empty — handle underflow\n    } else throw e;\n}","preventionTips":["Always check isEmpty() before pop().","Use while (!heap.isEmpty()) for drain loops.","Track element count when sharing the heap across producers/consumers."],"tags":["heap","priority-queue","javascript","empty-state","precondition"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}