| 1 | class PriorityQueue<T extends object> { |
| 2 | private _queue: Array<T>; |
| 3 | private _size: number = 0; |
| 4 | private _comparator: ((val: T, parent: T) => number) | null; |
| 5 | |
| 6 | constructor(initialCapacity?: number, comparator?: (val: T, parent: T) => number) { |
| 7 | const cap = initialCapacity ?? 11; |
| 8 | const com = comparator ?? null; |
| 9 | if (cap < 1) { |
| 10 | throw new Error('initial capacity must be greater than or equal to 1'); |
| 11 | } |
| 12 | this._queue = new Array<T>(cap); |
| 13 | this._comparator = com; |
| 14 | } |
| 15 | |
| 16 | private grow() { |
| 17 | const oldCapacity = this._size; |
| 18 | // Double size if small; else grow by 50% |
| 19 | const newCapacity = |
| 20 | oldCapacity + (oldCapacity < 64 ? oldCapacity + 2 : oldCapacity >> 1); |
| 21 | if (!Number.isSafeInteger(newCapacity)) { |
| 22 | throw new Error('OOM: new capacity not a safe integer'); |
| 23 | } |
| 24 | this._queue.length = newCapacity; |
| 25 | } |
| 26 | |
| 27 | private siftup(k: number, item: T): void { |
| 28 | if (this._comparator !== null) { |
| 29 | this.siftupUsingComparator(k, item); |
| 30 | } else { |
| 31 | this.siftupComparable(k, item); |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | /** |
| 36 | * siftup of heap |
| 37 | */ |
| 38 | private siftupUsingComparator(k: number, item: T): void { |
| 39 | while (k > 0) { |
| 40 | // find the parent |
| 41 | const parent = (k - 1) >>> 1; |
| 42 | const e = this._queue[parent] as T; |
| 43 | // compare item with it parent, if item's priority less, break siftup and insert |
| 44 | if (this._comparator!(item, e) >= 0) { |
| 45 | break; |
| 46 | } |
| 47 | // if item's priority more, make it's parent sink and proceed siftup |
| 48 | this._queue[k] = e; |
| 49 | k = parent; |
| 50 | } |
| 51 | // if k === 0, then we directly insert it |
| 52 | this._queue[k] = item; |
| 53 | } |
| 54 | |
| 55 | private siftupComparable(k: number, item: T): void { |
| 56 | while (k > 0) { |
| 57 | const parent = (k - 1) >>> 1; |
| 58 | const e = this._queue[parent] as T; |
| 59 | if (item.toString().localeCompare(e.toString()) >= 0) { |
| 60 | break; |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…