diff --git a/src/lib/PriorityQueue.hx b/src/lib/PriorityQueue.hx new file mode 100644 index 0000000..c014b7a --- /dev/null +++ b/src/lib/PriorityQueue.hx @@ -0,0 +1,69 @@ +package lib; + +using Lambda; + +abstract PriorityQueue(Array<{prio:Float, val:T}>) { + public inline function new() { + this = []; + } + + public function containsElement(element:T):Bool { + return this.exists((e) -> e.val == element); + } + + public function isEmpty():Bool { + return this.length == 0; + } + + public function insert(e:T, prio:Float) { + this.push({prio: prio, val: e}); + bubbleUp(this.length - 1); + } + + public function extractMin():Null { + if (this.length == 0) { + return null; + } + + swap(0, this.length - 1); + var minElement = this.pop(); + + bubbleDown(0); + + return minElement.val; + } + + private function bubbleUp(index:Int) { + var parentIndex:Int = Math.floor((index - 1) / 2); + + if (index > 0 && this[index].prio < this[parentIndex].prio) { + swap(index, parentIndex); + bubbleUp(parentIndex); + } + } + + private function bubbleDown(index:Int) { + var leftIndex = 2 * index + 1; + var rightIndex = 2 * index + 2; + var smallest = index; + + if (leftIndex < this.length && this[leftIndex].prio < this[smallest].prio) { + smallest = leftIndex; + } + + if (rightIndex < this.length && this[rightIndex].prio < this[smallest].prio) { + smallest = rightIndex; + } + + if (smallest != index) { + swap(index, smallest); + bubbleDown(smallest); + } + } + + private function swap(i:Int, j:Int) { + var tmp = this[i]; + this[i] = this[j]; + this[j] = tmp; + } +}