实现来自Go源码
从下往上调整堆
func siftupTimer(t []*timer, i int) bool {
if i >= len(t) {
return false
}
when := t[i].when
tmp := t[i]
for i > 0 { // 除非到达堆顶,否则每次和当前父节点进行比较,如果当前节点更小,那么交换
p := (i - 1) / 4 // parent
if when >= t[p].when {
break
}
t[i] = t[p]
t[i].i = i
i = p
}
if tmp != t[i] {
t[i] = tmp
t[i].i = i
}
return true
}
从上往下调整堆
func siftdownTimer(t []*timer, i int) bool {
n := len(t)
if i >= n {
return false
}
when := t[i].when
tmp := t[i]
for { // 这里的前一部分在确定哪个子节点最小,可以使用 for 循环遍历数组来优化
c := i*4 + 1 // left child
c3 := c + 2 // mid child
if c >= n {
break
}
w := t[c].when
if c+1 < n && t[c+1].when < w {
w = t[c+1].when
c++
}
if c3 < n {
w3 := t[c3].when
if c3+1 < n && t[c3+1].when < w3 {
w3 = t[c3+1].when
c3++
}
if w3 < w {
w = w3
c = c3
}
}
if w >= when { // 如果子节点最小值 >= 当前节点,则结束
break
}
t[i] = t[c]
t[i].i = i
i = c
}
if tmp != t[i] {
t[i] = tmp
t[i].i = i
}
return true
}
不同情况的小顶堆调整
插入新元素时,放置到堆的末尾,基于这个元素向上调整堆。
删除某个元素时
1. 如果是最后一个元素,那么直接删除。
2. 否则,把最后一个元素置为当前元素,基于当前元素,先向上调整堆,再向下调整堆。