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