UNPKG

async-await-queue

Version:

async/await simple priority queues

176 lines (150 loc) 4.16 kB
/** * Lighter version of * Heap.ts from https://github.com/ignlg/heap-js/blob/master/src/Heap.ts * heap-js by @ignlg */ export type Comparator<T> = (a: T, b: T) => number; export type IsEqual<T> = (e: T, o: T) => boolean; export const toInt = (n: number): number => ~~n; /** * Heap * @type {Class} */ export class Heap<T> { heapArray: Array<T> = []; _limit = 0; /** * Heap instance constructor. * @param {Function} compare Optional comparison function, defaults to Heap.minComparator<number> */ constructor(public compare: Comparator<T>) { } /* Static methods */ /** * Gets children indices for given index. * @param {Number} idx Parent index * @return {Array(Number)} Array of children indices */ static getChildrenIndexOf(idx: number): Array<number> { return [idx * 2 + 1, idx * 2 + 2]; } /** * Gets parent index for given index. * @param {Number} idx Children index * @return {Number | undefined} Parent index, -1 if idx is 0 */ static getParentIndexOf(idx: number): number { if (idx <= 0) { return -1; } const whichChildren = idx % 2 ? 1 : 2; return Math.floor((idx - whichChildren) / 2); } /* Instance methods */ /** * Adds an element to the heap. Aliases: `offer`. * Same as: push(element) * @param {any} element Element to be added * @return {Boolean} true */ push(element: T): boolean { this._sortNodeUp(this.heapArray.push(element) - 1); return true; } /** * Length of the heap. * @return {Number} */ length(): number { return this.heapArray.length; } /** * Top node. Aliases: `element`. * Same as: `top(1)[0]` * @return {any} Top node */ peek(): T | undefined { return this.heapArray[0]; } /** * Extract the top node (root). Aliases: `poll`. * @return {any} Extracted top node, undefined if empty */ pop(): T | undefined { const last = this.heapArray.pop(); if (this.length() > 0 && last !== undefined) { return this.replace(last); } return last; } /** * Pop the current peek value, and add the new item. * @param {any} element Element to replace peek * @return {any} Old peek */ replace(element: T): T { const peek = this.heapArray[0]; this.heapArray[0] = element; this._sortNodeDown(0); return peek; } /** * Size of the heap * @return {Number} */ size(): number { return this.length(); } /** * Move a node to a new index, switching places * @param {Number} j First node index * @param {Number} k Another node index */ _moveNode(j: number, k: number): void { [this.heapArray[j], this.heapArray[k]] = [this.heapArray[k], this.heapArray[j]]; } /** * Move a node down the tree (to the leaves) to find a place where the heap is sorted. * @param {Number} i Index of the node */ _sortNodeDown(i: number): void { let moveIt = i < this.heapArray.length - 1; const self = this.heapArray[i]; const getPotentialParent = (best: number, j: number) => { if (this.heapArray.length > j && this.compare(this.heapArray[j], this.heapArray[best]) < 0) { best = j; } return best; }; while (moveIt) { const childrenIdx = Heap.getChildrenIndexOf(i); const bestChildIndex = childrenIdx.reduce(getPotentialParent, childrenIdx[0]); const bestChild = this.heapArray[bestChildIndex]; if (typeof bestChild !== 'undefined' && this.compare(self, bestChild) > 0) { this._moveNode(i, bestChildIndex); i = bestChildIndex; } else { moveIt = false; } } } /** * Move a node up the tree (to the root) to find a place where the heap is sorted. * @param {Number} i Index of the node */ _sortNodeUp(i: number): void { let moveIt = i > 0; while (moveIt) { const pi = Heap.getParentIndexOf(i); if (pi >= 0 && this.compare(this.heapArray[pi], this.heapArray[i]) > 0) { this._moveNode(i, pi); i = pi; } else { moveIt = false; } } } }