utils/node_modules/@rushstack/node-core-library/lib/MinimumHeap.js
2024-02-07 01:33:07 -05:00

99 lines
3.5 KiB
JavaScript

"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
Object.defineProperty(exports, "__esModule", { value: true });
exports.MinimumHeap = void 0;
/**
* Implements a standard heap data structure for items of type T and a custom comparator.
* The root will always be the minimum value as determined by the comparator.
*
* @beta
*/
class MinimumHeap {
/**
* Constructs a new MinimumHeap instance.
* @param comparator - a comparator function that determines the order of the items in the heap.
* If the comparator returns a value less than zero, then `a` will be considered less than `b`.
* If the comparator returns zero, then `a` and `b` are considered equal.
* Otherwise, `a` will be considered greater than `b`.
*/
constructor(comparator) {
this._items = [];
this._comparator = comparator;
}
/**
* Returns the number of items in the heap.
* @returns the number of items in the heap.
*/
get size() {
return this._items.length;
}
/**
* Retrieves the root item from the heap without removing it.
* @returns the root item, or `undefined` if the heap is empty
*/
peek() {
return this._items[0];
}
/**
* Retrieves and removes the root item from the heap. The next smallest item will become the new root.
* @returns the root item, or `undefined` if the heap is empty
*/
poll() {
if (this.size > 0) {
const result = this._items[0];
const item = this._items.pop();
const size = this.size;
if (size === 0) {
// Short circuit in the trivial case
return result;
}
let index = 0;
let smallerChildIndex = 1;
while (smallerChildIndex < size) {
let smallerChild = this._items[smallerChildIndex];
const rightChildIndex = smallerChildIndex + 1;
if (rightChildIndex < size) {
const rightChild = this._items[rightChildIndex];
if (this._comparator(rightChild, smallerChild) < 0) {
smallerChildIndex = rightChildIndex;
smallerChild = rightChild;
}
}
if (this._comparator(smallerChild, item) < 0) {
this._items[index] = smallerChild;
index = smallerChildIndex;
smallerChildIndex = index * 2 + 1;
}
else {
break;
}
}
// Place the item in its final location satisfying the heap property
this._items[index] = item;
return result;
}
}
/**
* Pushes an item into the heap.
* @param item - the item to push
*/
push(item) {
let index = this.size;
while (index > 0) {
// Due to zero-based indexing the parent is not exactly a bit shift
const parentIndex = ((index + 1) >> 1) - 1;
const parent = this._items[parentIndex];
if (this._comparator(item, parent) < 0) {
this._items[index] = parent;
index = parentIndex;
}
else {
break;
}
}
this._items[index] = item;
}
}
exports.MinimumHeap = MinimumHeap;
//# sourceMappingURL=MinimumHeap.js.map