# 堆
堆(英语:Heap)是计算机科学中的一种特别的完全二叉树。若是满足以下特性,即可称为堆:“给定堆中任意节点 P 和 C,若 P 是 C 的母节点,那么 P 的值会小于等于(或大于等于)C 的值”。若母节点的值恒小于等于子节点的值,此堆称为最小堆(min heap);反之,若母节点的值恒大于等于子节点的值,此堆称为最大堆(max heap)。
堆存储数据是用一个一维数组存取,堆的每个节点的左边子节点索引是 i * 2 + 1
,右边是 i * 2 + 2
,父节点是 (i - 1) /2
,i
为当前节点在 head 数组中的索引
# 堆操作
操作 | 描述 |
---|---|
build | 创建一个空堆 |
insert | 向堆中插入一个新元素 |
update | 将新元素提升使其符合堆的性质 |
get | 获取当前堆顶元素的值 |
delete | 删除堆顶元素 |
heapify | 使删除堆顶元素的堆再次成为堆 |
# 代码实现(最小堆)
// 堆的每个节点的左边子节点索引是 i * 2 + 1,右边是 i * 2 + 2,父节点是 (i - 1) /2。i 为当前节点在head中的索引
class MinHeap {
constructor() {
this.heap = []
}
insert(value) {
this.heap.push(value)
this.shiftUp(this.heap.length - 1)
}
// 删除最小元素
deleteMin() {
return this.delete(0)
}
// 删除任意元素
delete(i) {
// 交换首位元素
const lastIndex = this.heap.length - 1
if (lastIndex < i) return
const r = this.heap[i]
this.heap[i] = this.heap[lastIndex]
this.heap[lastIndex] = r
this.heap.splice(lastIndex, 1)
this.shiftDown(i)
this.shiftUp(i)
return r
}
/**
* 子节点和父节点交换,从子级遍历到父级
* @param {*} i
*/
shiftUp(i) {
// 获取父级的下标
let parentIndex = parseInt((i - 1) / 2)
// 最大堆和最小堆,通过这里的比较运算符设置
while (this.heap[i] < this.heap[parentIndex]) {
const temp = this.heap[i]
this.heap[i] = this.heap[parentIndex]
this.heap[parentIndex] = temp
i = parentIndex
parentIndex = parseInt((i - 1) / 2)
}
}
/**
* 把最小值放到最顶端
* 父节点和子节点交换,从父级遍历到子级
* @param {*} i
*/
shiftDown(i) {
const size = this.heap.length - 1
while (true) {
let lChildIndex = i * 2 + 1
let rChildIndex = i * 2 + 2
const isSwapLeft = lChildIndex <= size && this.heap[i] > this.heap[lChildIndex]
const isSwapRight = rChildIndex <= size && this.heap[i] > this.heap[rChildIndex]
if (isSwapLeft) {
const temp = this.heap[i]
this.heap[i] = this.heap[lChildIndex]
this.heap[lChildIndex] = temp
i = lChildIndex
continue
} else if (isSwapRight) {
const temp = this.heap[i]
this.heap[i] = this.heap[rChildIndex]
this.heap[rChildIndex] = temp
i = rChildIndex
}
break
}
}
}
const h = new MinHeap()
h.insert(1)
h.insert(4)
h.insert(2)
h.insert(5)
h.insert(6)
h.insert(7)
h.insert(3)
// h.insert(81)
console.log(h.heap)
h.delete(3)
console.log(h.heap)