Skip to content

Instantly share code, notes, and snippets.

@jcready
Created February 18, 2018 18:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcready/1b52f41734b139ec72a07801ecfc5d39 to your computer and use it in GitHub Desktop.
Save jcready/1b52f41734b139ec72a07801ecfc5d39 to your computer and use it in GitHub Desktop.
A priority queue using a private binary heap
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