Created
February 18, 2018 18:22
-
-
Save jcready/1b52f41734b139ec72a07801ecfc5d39 to your computer and use it in GitHub Desktop.
A priority queue using a private binary heap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const PriorityQueue = (() => { | |
const parent = i => ((i + 1) >>> 1) - 1 | |
const left = i => (i << 1) + 1 | |
const right = i => (i + 1) << 1 | |
const privateMap = new WeakMap() | |
const $ = privateMap.get.bind(privateMap) | |
const swap = (self, i, j) => { | |
const h = $(self).heap | |
const tmp = h[i] | |
h[i] = h[j] | |
h[j] = tmp | |
} | |
const siftUp = (self) => { | |
const { heap, greater } = $(self) | |
let idx = heap.length - 1 | |
let prev = parent(idx) | |
while (idx > 0 && greater(idx, parent(idx))) { | |
swap(self, idx, parent(idx)) | |
idx = parent(idx) | |
} | |
} | |
const siftDown = (self) => { | |
const { heap, greater } = $(self) | |
const size = heap.length | |
let idx = 0 | |
while ( | |
left(idx) < size && greater(left(idx), idx) || | |
right(idx) < size && greater(right(idx), idx) | |
) { | |
let max = left(idx) | |
if (right(idx) < size && greater(right(idx), left(idx))) { | |
max = right(idx) | |
} | |
swap(self, idx, max) | |
idx = max | |
} | |
} | |
return class PriorityQueue { | |
constructor(comparator = (a,b) => a - b) { | |
const heap = [] | |
privateMap.set(this, { | |
heap, | |
greater: (i, j) => comparator(heap[i].priority, heap[j].priority) > 0 | |
}) | |
} | |
size () { | |
return $(this).heap.length | |
} | |
peek () { | |
return $(this).heap[0].value | |
} | |
enqueue (value, priority) { | |
$(this).heap.push({ value, priority }) | |
siftUp(this) | |
} | |
dequeue () { | |
const { heap } = $(this) | |
if (heap.length) { | |
const result = heap.shift() | |
const last = heap.length - 1 | |
if (last > 0) swap(this, 0, last) | |
siftDown(this) | |
return result.value | |
} | |
} | |
} | |
})() | |
/* | |
q = new PriorityQueue() | |
q.enqueue('a', 2) | |
q.enqueue('b', 3) | |
q.enqueue('c', 1) | |
q.peek() // 'b' | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment