{"record":{"id":"a5a210f14945a57f","repo":"krahets/hello-algo","slug":"heap-is-empty-a5a210","errorCode":null,"errorMessage":"Heap is empty.","messagePattern":"Heap is empty\\.","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"ru/codes/typescript/chapter_heap/my_heap.ts","lineNumber":84,"sourceCode":"\n    /* Начиная с узла i, выполнить просеивание снизу вверх */\n    private siftUp(i: number): void {\n        while (true) {\n            // Получение родительского узла для узла i\n            const p = this.parent(i);\n            // Завершить heapify, когда «корневой узел уже пройден» или «узел не требует исправления»\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    public pop(): number {\n        // Обработка пустого случая\n        if (this.isEmpty()) throw new RangeError('Heap is empty.');\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    private siftDown(i: number): void {\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":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/krahets/hello-algo/blob/69932aed1891a7b7f6a0de88cd116d3fe13e7032/ru/codes/typescript/chapter_heap/my_heap.ts#L66-L102","documentation":"Thrown by pop() on a max-heap when the heap contains no elements (isEmpty() is true). It prevents swapping/sifting on an undefined root and returning undefined as a number. Thrown as a RangeError to signal an empty-collection access.","triggerScenarios":"Calling pop() more times than elements were pushed; calling pop() immediately after construction with no inserts; draining the heap in a loop without a termination check.","commonSituations":"Priority-queue consumers that pop in a while(true) loop and forget the empty check; using the heap to feed an algorithm that underestimates how many elements remain.","solutions":["Always check heap.isEmpty() before calling pop().","Drive the drain loop with while (!heap.isEmpty()) { ... heap.pop() ... }.","If pop must be called defensively, wrap it in try/catch and treat empty as a sentinel.","Ensure inserts (push) precede pops by verifying the count logic."],"exampleFix":"// before\nwhile (true) {\n    const v = heap.pop(); // throws when drained\n}\n\n// after\nwhile (!heap.isEmpty()) {\n    const v = 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 instanceof RangeError && e.message === 'Heap is empty.') {\n        // handle empty heap\n    } else throw e;\n}","preventionTips":["Always pair pop() with an isEmpty() check.","Drain heaps with while (!heap.isEmpty()).","Track the number of inserted elements when feeding drain loops."],"tags":["heap","typescript","empty-state","priority-queue","validation"],"backgroundTag":null,"analyzedSha":"69932aed1891a7b7f6a0de88cd116d3fe13e7032","analyzedAt":"2026-08-13T23:02:37.581Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}