UNPKG

dastal

Version:

Data Structures & Algorithms implementations

193 lines 6.05 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BinaryHeap = void 0; const arrayUtils_1 = require("src/utils/arrayUtils"); const env_1 = require("src/env"); const utils_1 = require("./utils"); /** * A binary heap is a heap implemented as a binary tree with an additional shape property * ([source](https://en.wikipedia.org/wiki/Binary_heap)). * * **Shape property**: Must be a complete binary tree. This means all levels of the tree * (except possibly the last one) are fully filled. If the last level of the tree is incomplete, * the nodes of that level are filled from left to right. * * #### Complexity * * | Property | Average | Worst | * | :------- | :------ | :---- | * | Space | O(n) | O(n) * | Push | O(1) | O(log n) * | Peek | O(1) | O(1) * | Pop | O(log n)| O(log n) * | Search | O(n) | O(n) */ class BinaryHeap { /** * Instantiate a heap. * * @param compareFn - The function to determine the order of elements. * @param elements - A set of elements to initialize the list with. */ constructor(compareFn, elements) { this.compare = compareFn; this.array = []; this.addAll(elements ?? []); } addAll(elements) { const array = this.array; const length = array.length; if (arrayUtils_1.isArray(elements)) { if (array.length + elements.length > env_1.MAX_ARRAY_LENGTH) { throw new RangeError('Invalid heap length'); } for (let i = 0; i < elements.length; ++i) { array.push(elements[i]); } } else { for (const element of elements) { if (array.length >= env_1.MAX_ARRAY_LENGTH) { throw new RangeError('Invalid heap length'); } array.push(element); } } // Update the heap if (length < array.length) { utils_1.heapify(this.compare, array); } return array.length; } clear() { this.array.length = 0; } comparator() { return this.compare; } contains(element) { return this.array.indexOf(element) >= 0; } delete(element) { const index = this.array.indexOf(element); if (index < 0) { return false; } // If deleting the last value const last = this.array.pop(); if (index >= this.array.length) { return true; } // Add the last value to the // deleted index and update the heap this.array[index] = last; utils_1.sinkDown(index, this.compare, this.array); utils_1.bubbleUp(index, this.compare, this.array); return true; } merge(heap) { const array = this.array; if (heap.size < 1) { return this; } if (array.length + heap.size > env_1.MAX_ARRAY_LENGTH) { throw new RangeError('Invalid heap length'); } for (const element of heap) { array.push(element); } utils_1.heapify(this.compare, array); return this; } peek() { return this.array.length > 0 ? this.array[0] : undefined; } pop() { if (this.array.length < 1) { return undefined; } // Get the root and the last value const value = this.array[0]; const last = this.array.pop(); // If value != last if (this.array.length > 0) { // Move the last value to the root and update the heap this.array[0] = last; utils_1.sinkDown(0, this.compare, this.array); } return value; } push(value) { // Add new value to the end of the heap this.array.push(value); // Update the heap utils_1.bubbleUp(this.array.length - 1, this.compare, this.array); return this.size; } pushPop(value) { // If empty or value is <= to root if (this.array.length < 1 || this.compare(value, this.array[0]) <= 0) { return value; } // Swap the root and value const root = this.array[0]; this.array[0] = value; utils_1.sinkDown(0, this.compare, this.array); return root; } replace(value) { // If empty if (this.array.length < 1) { this.array.push(value); return undefined; } // Swap the root with value const root = this.array[0]; this.array[0] = value; value = root; // Update the heap utils_1.sinkDown(0, this.compare, this.array); return value; } get size() { return this.array.length; } *sorted() { if (this.array.length < 1) { return; } const array = this.array; const heap = new BinaryHeap((a, b) => this.compare(array[a], array[b]), [0]); do { let index = heap.pop(); if (index < array.length) { yield array[index]; index = 2 * index + 1; index < array.length && heap.push(index); ++index < array.length && heap.push(index); } } while (heap.size > 0); } /** * Receive an iterator through the list. * * **Note:** Unexpected behavior can occur if the collection is modified during iteration. * * @returns An iterator through the list */ [Symbol.iterator]() { return this.array[Symbol.iterator](); } update(curElement, newElement) { const index = this.array.indexOf(curElement); if (index < 0) { return false; } this.array[index] = newElement; utils_1.sinkDown(index, this.compare, this.array); utils_1.bubbleUp(index, this.compare, this.array); return true; } } exports.BinaryHeap = BinaryHeap; //# sourceMappingURL=binaryHeap.js.map