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
131 lines
4.0 KiB
12 months ago
|
// 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(" ")}]`;
|
||
|
}
|
||
|
}
|