UNPKG

@thermopylae/lib.cache

Version:
131 lines (130 loc) 3.72 kB
const HEAP_NODE_IDX_SYM = Symbol('HEAP_NODE_INDEX_SYMBOL'); class Heap { comparator; nodes; constructor(comparator) { this.comparator = comparator; this.nodes = []; } push(node) { this.pushNodeIntoInternalCollection(node); this.propagateUp(node); } peek() { return this.root; } pop() { const lastChildNode = this.nodes.pop(); let nodeToBeReturned; if (this.nodes.length) { nodeToBeReturned = this.root; this.root = lastChildNode; this.propagateDown(lastChildNode); } else { nodeToBeReturned = lastChildNode; } if (nodeToBeReturned) { Heap.detachMetadata(nodeToBeReturned); } return nodeToBeReturned; } delete(node) { const { fartestRightNode } = this; if (node === fartestRightNode) { this.nodes.length -= 1; } else { this.swap(node, fartestRightNode); this.nodes.length -= 1; if (this.propagateDown(fartestRightNode) === fartestRightNode) { this.propagateUp(fartestRightNode); } } Heap.detachMetadata(node); } heapifyUpdatedNode(node) { if (this.propagateDown(node) === node) { this.propagateUp(node); } } clear() { this.nodes.length = 0; } get size() { return this.nodes.length; } static isPartOfHeap(node) { return node[HEAP_NODE_IDX_SYM] != null; } get root() { return this.nodes[0]; } set root(node) { this.nodes[0] = node; node[HEAP_NODE_IDX_SYM] = 0; } get fartestRightNode() { return this.nodes[this.nodes.length - 1]; } propagateUp(node) { let parent; while (Heap.isNotRoot(node)) { parent = this.parent(node); if (this.comparator(node, parent) < 0) { this.swap(node, parent); } else { return; } } } propagateDown(node) { let leftChild = this.leftChild(node); let rightChild; let largest; while (leftChild) { largest = node; if (this.comparator(leftChild, largest) < 0) { largest = leftChild; } rightChild = this.rightSibling(leftChild); if (rightChild && this.comparator(rightChild, largest) < 0) { largest = rightChild; } if (largest === node) { return node; } this.swap(node, largest); leftChild = this.leftChild(node); } return node; } swap(first, second) { this.nodes[first[HEAP_NODE_IDX_SYM]] = second; this.nodes[second[HEAP_NODE_IDX_SYM]] = first; const aux = first[HEAP_NODE_IDX_SYM]; first[HEAP_NODE_IDX_SYM] = second[HEAP_NODE_IDX_SYM]; second[HEAP_NODE_IDX_SYM] = aux; } pushNodeIntoInternalCollection(node) { this.nodes.push(node); node[HEAP_NODE_IDX_SYM] = this.nodes.length - 1; } leftChild(parentNode) { return this.nodes[parentNode[HEAP_NODE_IDX_SYM] * 2 + 1]; } rightSibling(childNode) { return this.nodes[childNode[HEAP_NODE_IDX_SYM] + 1]; } parent(childNode) { return this.nodes[(childNode[HEAP_NODE_IDX_SYM] - 1) >> 1]; } static isNotRoot(node) { return node[HEAP_NODE_IDX_SYM] !== 0; } static detachMetadata(node) { node[HEAP_NODE_IDX_SYM] = undefined; } } export { Heap, HEAP_NODE_IDX_SYM };