You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
4.0 KiB

// translated by esbuild to js. original typescript source MIT licensed at https://github.com/luciopaiva/heapify
const ROOT_INDEX = 1;
class MinQueue {
constructor(capacity = 64, keys = [], priorities = [], KeysBackingArrayType = Uint32Array, PrioritiesBackingArrayType = Uint32Array) {
this._capacity = capacity;
this._keys = new KeysBackingArrayType(capacity + ROOT_INDEX);
this._priorities = new PrioritiesBackingArrayType(capacity + ROOT_INDEX);
this._hasPoppedElement = false;
if (keys.length !== priorities.length) {
throw new Error("Number of keys does not match number of priorities provided.");
}
if (capacity < keys.length) {
throw new Error("Capacity less than number of provided keys.");
}
for (let i = 0; i < keys.length; i++) {
this._keys[i + ROOT_INDEX] = keys[i];
this._priorities[i + ROOT_INDEX] = priorities[i];
}
this.length = keys.length;
for (let i = keys.length >>> 1; i >= ROOT_INDEX; i--) {
this.bubbleDown(i);
}
}
get capacity() {
return this._capacity;
}
clear() {
this.length = 0;
this._hasPoppedElement = false;
}
bubbleUp(index) {
const key = this._keys[index];
const priority = this._priorities[index];
while (index > ROOT_INDEX) {
const parentIndex = index >>> 1;
if (this._priorities[parentIndex] <= priority) {
break;
}
this._keys[index] = this._keys[parentIndex];
this._priorities[index] = this._priorities[parentIndex];
index = parentIndex;
}
this._keys[index] = key;
this._priorities[index] = priority;
}
bubbleDown(index) {
const key = this._keys[index];
const priority = this._priorities[index];
const halfLength = ROOT_INDEX + (this.length >>> 1);
const lastIndex = this.length + ROOT_INDEX;
while (index < halfLength) {
const left = index << 1;
let childPriority = this._priorities[left];
let childKey = this._keys[left];
let childIndex = left;
const right = left + 1;
if (right < lastIndex) {
const rightPriority = this._priorities[right];
if (rightPriority < childPriority) {
childPriority = rightPriority;
childKey = this._keys[right];
childIndex = right;
}
}
if (childPriority >= priority) {
break;
}
this._keys[index] = childKey;
this._priorities[index] = childPriority;
index = childIndex;
}
this._keys[index] = key;
this._priorities[index] = priority;
}
push(key, priority) {
if (this.length === this._capacity) {
throw new Error("Heap has reached capacity, can't push new items");
}
if (this._hasPoppedElement) {
this._keys[ROOT_INDEX] = key;
this._priorities[ROOT_INDEX] = priority;
this.length++;
this.bubbleDown(ROOT_INDEX);
this._hasPoppedElement = false;
} else {
const pos = this.length + ROOT_INDEX;
this._keys[pos] = key;
this._priorities[pos] = priority;
this.length++;
this.bubbleUp(pos);
}
}
pop() {
if (this.length === 0) {
return void 0;
}
this.removePoppedElement();
this.length--;
this._hasPoppedElement = true;
return this._keys[ROOT_INDEX];
}
peekPriority() {
this.removePoppedElement();
return this._priorities[ROOT_INDEX];
}
peek() {
this.removePoppedElement();
return this._keys[ROOT_INDEX];
}
removePoppedElement() {
if (this._hasPoppedElement) {
this._keys[ROOT_INDEX] = this._keys[this.length + ROOT_INDEX];
this._priorities[ROOT_INDEX] = this._priorities[this.length + ROOT_INDEX];
this.bubbleDown(ROOT_INDEX);
this._hasPoppedElement = false;
}
}
get size() {
return this.length;
}
dumpRawPriorities() {
this.removePoppedElement();
const result = Array(this.length - ROOT_INDEX);
for (let i = 0; i < this.length; i++) {
result[i] = this._priorities[i + ROOT_INDEX];
}
return `[${result.join(" ")}]`;
}
}