function create (maxLength=1000) { return { arr: new Array(maxLength), length: 0, maxLength, } } function queue (heap, item, priority) { if (priority === undefined) throw new Error('must include priority when queueing') if (_findIndex(heap, item) >= 0) { del(heap, item) } if (heap.length === heap.maxLength) { return } heap.arr[heap.length] = { item, priority } heap.length++ _upHeap(heap, heap.length-1) } // traverse up the heap from a starting index // // heap // index to start at function _upHeap (heap, index) { while (index > 0) { let parentIdx if (index % 2 === 0) parentIdx = (index - 2) / 2 else parentIdx = (index - 1) / 2 // if the parent is greater than the current node, stop because we've corrected the heap if (heap.arr[parentIdx].priority >= heap.arr[index].priority) return _swap(heap.arr, index, parentIdx) index = parentIdx } } // get and remove highest priority item from the heap function dequeue (heap) { if (heap.length === 0) return const max = heap.arr[0].item heap.length-- heap.arr[0] = heap.arr[heap.length] _downHeap(heap, 0) return max } // traverse down the heap from a starting index // // heap // index to start at function _downHeap (heap, index) { while (index < heap.length) { const left = index * 2 + 1 const right = index * 2 + 2 let largest = index if (left < heap.length && heap.arr[left].priority > heap.arr[largest].priority) largest = left if (right < heap.length && heap.arr[right].priority > heap.arr[largest].priority) largest = right if (largest === index) return _swap(heap.arr, index, largest) index = largest } } function _swap (arr, i, j) { const tmp = arr[i] arr[i] = arr[j] arr[j] = tmp } function clear (heap) { heap.length = 0 } function isEmpty (heap) { return heap.length === 0 } function peek (heap) { if (!heap.length) return return heap.arr[0].item } function del (heap, item) { const ind = _findIndex(heap, item) if (ind < 0) throw new Error('key does not exist in priority queue!') const tmp = heap.arr[ind] heap.arr[ind] = heap.arr[heap.length-1] heap.arr[heap.length-1] = tmp if (heap.arr[ind].priority > heap.arr[heap.length-1].priority) _upHeap(heap, ind) else if (heap.arr[ind].priority < heap.arr[heap.length-1].priority) _downHeap(heap, ind) heap.length-- } function _findIndex (heap, item) { for (let i=0; i < heap.length; i++) if (heap.arr[i].item === item) return i return -1 } function list (heap) { if (!heap.length) return [ ] const result = [ ] for (let i=0; i < heap.length; i++) result[i] = heap.arr[i].item return result } export default { create, queue, dequeue, clear, isEmpty, peek, delete: del, list }