11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst { 41cb0ef41Sopenharmony_ci Array, 51cb0ef41Sopenharmony_ci} = primordials; 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci// The PriorityQueue is a basic implementation of a binary heap that accepts 81cb0ef41Sopenharmony_ci// a custom sorting function via its constructor. This function is passed 91cb0ef41Sopenharmony_ci// the two nodes to compare, similar to the native Array#sort. Crucially 101cb0ef41Sopenharmony_ci// this enables priority queues that are based on a comparison of more than 111cb0ef41Sopenharmony_ci// just a single criteria. 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_cimodule.exports = class PriorityQueue { 141cb0ef41Sopenharmony_ci #compare = (a, b) => a - b; 151cb0ef41Sopenharmony_ci #heap = new Array(64); 161cb0ef41Sopenharmony_ci #setPosition; 171cb0ef41Sopenharmony_ci #size = 0; 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci constructor(comparator, setPosition) { 201cb0ef41Sopenharmony_ci if (comparator !== undefined) 211cb0ef41Sopenharmony_ci this.#compare = comparator; 221cb0ef41Sopenharmony_ci if (setPosition !== undefined) 231cb0ef41Sopenharmony_ci this.#setPosition = setPosition; 241cb0ef41Sopenharmony_ci } 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci insert(value) { 271cb0ef41Sopenharmony_ci const heap = this.#heap; 281cb0ef41Sopenharmony_ci const pos = ++this.#size; 291cb0ef41Sopenharmony_ci heap[pos] = value; 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci if (heap.length === pos) 321cb0ef41Sopenharmony_ci heap.length *= 2; 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci this.percolateUp(pos); 351cb0ef41Sopenharmony_ci } 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci peek() { 381cb0ef41Sopenharmony_ci return this.#heap[1]; 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci percolateDown(pos) { 421cb0ef41Sopenharmony_ci const compare = this.#compare; 431cb0ef41Sopenharmony_ci const setPosition = this.#setPosition; 441cb0ef41Sopenharmony_ci const heap = this.#heap; 451cb0ef41Sopenharmony_ci const size = this.#size; 461cb0ef41Sopenharmony_ci const item = heap[pos]; 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci while (pos * 2 <= size) { 491cb0ef41Sopenharmony_ci let childIndex = pos * 2 + 1; 501cb0ef41Sopenharmony_ci if (childIndex > size || compare(heap[pos * 2], heap[childIndex]) < 0) 511cb0ef41Sopenharmony_ci childIndex = pos * 2; 521cb0ef41Sopenharmony_ci const child = heap[childIndex]; 531cb0ef41Sopenharmony_ci if (compare(item, child) <= 0) 541cb0ef41Sopenharmony_ci break; 551cb0ef41Sopenharmony_ci if (setPosition !== undefined) 561cb0ef41Sopenharmony_ci setPosition(child, pos); 571cb0ef41Sopenharmony_ci heap[pos] = child; 581cb0ef41Sopenharmony_ci pos = childIndex; 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci heap[pos] = item; 611cb0ef41Sopenharmony_ci if (setPosition !== undefined) 621cb0ef41Sopenharmony_ci setPosition(item, pos); 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci percolateUp(pos) { 661cb0ef41Sopenharmony_ci const heap = this.#heap; 671cb0ef41Sopenharmony_ci const compare = this.#compare; 681cb0ef41Sopenharmony_ci const setPosition = this.#setPosition; 691cb0ef41Sopenharmony_ci const item = heap[pos]; 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci while (pos > 1) { 721cb0ef41Sopenharmony_ci const parent = heap[pos / 2 | 0]; 731cb0ef41Sopenharmony_ci if (compare(parent, item) <= 0) 741cb0ef41Sopenharmony_ci break; 751cb0ef41Sopenharmony_ci heap[pos] = parent; 761cb0ef41Sopenharmony_ci if (setPosition !== undefined) 771cb0ef41Sopenharmony_ci setPosition(parent, pos); 781cb0ef41Sopenharmony_ci pos = pos / 2 | 0; 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci heap[pos] = item; 811cb0ef41Sopenharmony_ci if (setPosition !== undefined) 821cb0ef41Sopenharmony_ci setPosition(item, pos); 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci removeAt(pos) { 861cb0ef41Sopenharmony_ci const heap = this.#heap; 871cb0ef41Sopenharmony_ci const size = --this.#size; 881cb0ef41Sopenharmony_ci heap[pos] = heap[size + 1]; 891cb0ef41Sopenharmony_ci heap[size + 1] = undefined; 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci if (size > 0 && pos <= size) { 921cb0ef41Sopenharmony_ci if (pos > 1 && this.#compare(heap[pos / 2 | 0], heap[pos]) > 0) 931cb0ef41Sopenharmony_ci this.percolateUp(pos); 941cb0ef41Sopenharmony_ci else 951cb0ef41Sopenharmony_ci this.percolateDown(pos); 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci shift() { 1001cb0ef41Sopenharmony_ci const heap = this.#heap; 1011cb0ef41Sopenharmony_ci const value = heap[1]; 1021cb0ef41Sopenharmony_ci if (value === undefined) 1031cb0ef41Sopenharmony_ci return; 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci this.removeAt(1); 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci return value; 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci}; 110