堆是在节点上存储数据的完全二叉树, 小顶堆是把对中最小值一直保持在堆顶的树型结构。其中主要通过替换父子节点来实现
- 向上筛选: 将新的值插入到堆尾,并通过与父节点(循环)比较来对换位置。
- 向下筛选: 将堆尾放入到已弹出的堆顶部,通过与子节点(循环)比较来对换位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| class PriorityQue { constructor(heap = []) { this.heap = heap this.build() }
getSize() { return this.heap.length }
upward(i) { while (this._parent(i) >= 0 && i > 0) { if (this.heap[this._parent(i)] > this.heap[i]) { let tmp = this.heap[i] this.heap[i] = this.heap[this._parent(i)] this.heap[this._parent(i)] = tmp } i = this._parent(i) } }
downward(i) { while (i * 2 <= this.getSize()) { let idx = this.minChild(i)
if (this.heap[i] > this.heap[idx]) { let tmp = this.heap[idx] this.heap[idx] = this.heap[i] this.heap[i] = tmp } i = idx > 0 ? idx : 1 } }
minChild(i) { let left_idx = i * 2 let right_idx = i * 2 + 1 if (right_idx > this.getSize()) { return left_idx } else if (this.heap[left_idx] < this.heap[right_idx]) { return left_idx } else { return right_idx } }
_parent(i) { return Math.floor(i / 2) }
enqueue(e) { this.heap.push(e) this.upward(this.getSize()) }
dequeue() { let e = this.heap[0] this.heap[0] = this.heap[this.getSize() - 1] this.heap.pop() this.downward(0) return e }
build() { let i = this.getSize() while (i > 0) { this.upward(i) i -= 1 } } }
let q = new PriorityQue([5, 4, 3, 2, 1]) console.log(q) for (let i = 0; i < 5; i++) { q.dequeue() }
|