UNPKG

typescript-collections

Version:

A complete, fully tested data structure library written in TypeScript.

227 lines 7.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var collections = require("./util"); var arrays = require("./arrays"); var Heap = /** @class */ (function () { /** * Creates an empty Heap. * @class * <p>A heap is a binary tree, where the nodes maintain the heap property: * each node is smaller than each of its children and therefore a MinHeap * This implementation uses an array to store elements.</p> * <p>If the inserted elements are custom objects a compare function must be provided, * at construction time, otherwise the <=, === and >= operators are * used to compare elements. Example:</p> * * <pre> * function compare(a, b) { * if (a is less than b by some ordering criterion) { * return -1; * } if (a is greater than b by the ordering criterion) { * return 1; * } * // a must be equal to b * return 0; * } * </pre> * * <p>If a Max-Heap is wanted (greater elements on top) you can a provide a * reverse compare function to accomplish that behavior. Example:</p> * * <pre> * function reverseCompare(a, b) { * if (a is less than b by some ordering criterion) { * return 1; * } if (a is greater than b by the ordering criterion) { * return -1; * } * // a must be equal to b * return 0; * } * </pre> * * @constructor * @param {function(Object,Object):number=} compareFunction optional * function used to compare two elements. Must return a negative integer, * zero, or a positive integer as the first argument is less than, equal to, * or greater than the second. */ function Heap(compareFunction) { /** * Array used to store the elements of the heap. * @type {Array.<Object>} * @private */ this.data = []; this.compare = compareFunction || collections.defaultCompare; } /** * Returns the index of the left child of the node at the given index. * @param {number} nodeIndex The index of the node to get the left child * for. * @return {number} The index of the left child. * @private */ Heap.prototype.leftChildIndex = function (nodeIndex) { return (2 * nodeIndex) + 1; }; /** * Returns the index of the right child of the node at the given index. * @param {number} nodeIndex The index of the node to get the right child * for. * @return {number} The index of the right child. * @private */ Heap.prototype.rightChildIndex = function (nodeIndex) { return (2 * nodeIndex) + 2; }; /** * Returns the index of the parent of the node at the given index. * @param {number} nodeIndex The index of the node to get the parent for. * @return {number} The index of the parent. * @private */ Heap.prototype.parentIndex = function (nodeIndex) { return Math.floor((nodeIndex - 1) / 2); }; /** * Returns the index of the smaller child node (if it exists). * @param {number} leftChild left child index. * @param {number} rightChild right child index. * @return {number} the index with the minimum value or -1 if it doesn't * exists. * @private */ Heap.prototype.minIndex = function (leftChild, rightChild) { if (rightChild >= this.data.length) { if (leftChild >= this.data.length) { return -1; } else { return leftChild; } } else { if (this.compare(this.data[leftChild], this.data[rightChild]) <= 0) { return leftChild; } else { return rightChild; } } }; /** * Moves the node at the given index up to its proper place in the heap. * @param {number} index The index of the node to move up. * @private */ Heap.prototype.siftUp = function (index) { var parent = this.parentIndex(index); while (index > 0 && this.compare(this.data[parent], this.data[index]) > 0) { arrays.swap(this.data, parent, index); index = parent; parent = this.parentIndex(index); } }; /** * Moves the node at the given index down to its proper place in the heap. * @param {number} nodeIndex The index of the node to move down. * @private */ Heap.prototype.siftDown = function (nodeIndex) { //smaller child index var min = this.minIndex(this.leftChildIndex(nodeIndex), this.rightChildIndex(nodeIndex)); while (min >= 0 && this.compare(this.data[nodeIndex], this.data[min]) > 0) { arrays.swap(this.data, min, nodeIndex); nodeIndex = min; min = this.minIndex(this.leftChildIndex(nodeIndex), this.rightChildIndex(nodeIndex)); } }; /** * Retrieves but does not remove the root element of this heap. * @return {*} The value at the root of the heap. Returns undefined if the * heap is empty. */ Heap.prototype.peek = function () { if (this.data.length > 0) { return this.data[0]; } else { return undefined; } }; /** * Adds the given element into the heap. * @param {*} element the element. * @return true if the element was added or fals if it is undefined. */ Heap.prototype.add = function (element) { if (collections.isUndefined(element)) { return false; } this.data.push(element); this.siftUp(this.data.length - 1); return true; }; /** * Retrieves and removes the root element of this heap. * @return {*} The value removed from the root of the heap. Returns * undefined if the heap is empty. */ Heap.prototype.removeRoot = function () { if (this.data.length > 0) { var obj = this.data[0]; this.data[0] = this.data[this.data.length - 1]; this.data.splice(this.data.length - 1, 1); if (this.data.length > 0) { this.siftDown(0); } return obj; } return undefined; }; /** * Returns true if this heap contains the specified element. * @param {Object} element element to search for. * @return {boolean} true if this Heap contains the specified element, false * otherwise. */ Heap.prototype.contains = function (element) { var equF = collections.compareToEquals(this.compare); return arrays.contains(this.data, element, equF); }; /** * Returns the number of elements in this heap. * @return {number} the number of elements in this heap. */ Heap.prototype.size = function () { return this.data.length; }; /** * Checks if this heap is empty. * @return {boolean} true if and only if this heap contains no items; false * otherwise. */ Heap.prototype.isEmpty = function () { return this.data.length <= 0; }; /** * Removes all of the elements from this heap. */ Heap.prototype.clear = function () { this.data.length = 0; }; /** * Executes the provided function once for each element present in this heap in * no particular order. * @param {function(Object):*} callback function to execute, it is * invoked with one argument: the element value, to break the iteration you can * optionally return false. */ Heap.prototype.forEach = function (callback) { arrays.forEach(this.data, callback); }; return Heap; }()); exports.default = Heap; //# sourceMappingURL=Heap.js.map