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.
130 lines
4.0 KiB
130 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(" ")}]`; |
|
} |
|
}
|
|
|