什么是堆?
堆是一个完全二叉树的数据结构!
| 普通队列 | 优先队列(堆) |
|---|---|
| 从头出队列 | 从头弹出 |
| 从尾入队列 | 从尾插入 |
| 先进先出 | 每次出队权值(最大值/最小值) |
| 数组实现 | 数组实现(数据结构上看成是堆) |
堆的用处
堆怎么实现?
之前实现的最小堆可回看
首先我们要找到左右子节点和父节点的关系。 下图是当根节点为索引0时,各子节点的索引示意图
// 已知父节点parentIndex 求左右子节点
leftIndex = parentIndex * 2 + 1
rightIndex = parentIndex * 2 + 2
// 已知子节点求父节点
leftIndex or rightIndex 都看成 childIndex
parentIndex = (childIndex - 1) >> 1 // 无论左右取整后得到都是一样的
然后我们根据节点关系构建堆(一般使用大顶堆)
class MinHeap {
constructor(compare ) {
this.data = [];
this.compare = compare
}
peek() {
if(this.size() == 0) return null
return this.data[0];
}
size() {
return this.data.length;
}
push(x) {
this.data.push(x);
this.liftUp(this.data.length - 1);
}
swap(i, j) {
[this.data[i], this.data[j]] = [this.data[j], this.data[i]];
}
liftUp(ind) {
while (ind && this.compare(this.data[ind], this.data[(ind -1) >> 1])) {
this.swap(ind, (ind -1) >> 1);
ind = (ind -1) >> 1;
}
}
pop() {
if(this.size() == 0)return null
const last = this.data.pop();
if (this.size() != 0) {
this.data[0] = last;
this.liftDown(0);
}
return last
}
liftDown(ind) {
// 先和左比
let n = this.data.length-1;
while (ind * 2 + 1 <= n ) {
let tmp = ind
if(this.compare(this.data[ind * 2 + 1] ,this.data[tmp])) tmp = ind * 2 + 1
if(ind * 2 + 2 <= n && this.compare(this.data[ind * 2 + 2 ], this.data[tmp]))tmp = ind * 2 +2
if(ind == tmp)break
this.swap(ind, tmp)
ind= tmp
}
}
}