以大顶堆进行说明
//定义一个堆
type Heap []int
//传入要交换的两个节点的索引,将两个节点的值进行交换
func (h Heap) swap(i, j int) {
h[i], h[j] = h[j], h[i]
return
}
//传入要比较的两个节点的索引,前者的值大于后者就返回true
func (h Heap) bigger(i, j int) bool {
return h[i] > h[j]
}
//节点从下层往根节点的方向进行交换,传入的是节点的索引
func (h Heap) up(i int) {
for {
//得到父节点的索引
f := (i - 1) / 2
// i==f的情况是i节点已经到达了根节点,除此之外小于父节点的值时也说明已经到了该到的地方。
if i == f || h.bigger(f, i) {
break
}
//将当前节点值和父节点值进行交换
h.swap(f, i)
//将节点改为父节点继续进行交换
i = f
}
return
}
//节点从上层往叶节点的方向进行交换,传入的是节点的索引
func (h Heap) down(i int) {
for {
//分别得到当前节点左右儿子节点的索引l和r
l, r := 2*i+1, 2*i+2
//如果l越界了说明当前节点已经是叶节点了
if l >= len(h) {
break
}
j := l
//找到左右儿子节点值中更大的一个
if r < len(h) && h.bigger(r, l) {
j = r
}
//如果当前节点值比两个儿子的值都大说明已经当前节点到了该到的地方
if h.bigger(i, j) {
break
}
//将当前节点值和较大儿子的值进行交换
h.swap(i, j)
//将节点改为儿子节点,继续进行交换
i = j
}
return
}
//将一个新的值加入到堆中,先加入到数组中的最后,再进行up操作
func (h *Heap) Push(x int) {
*h = append(*h, x)
h.up(len(*h) - 1)
return
}
//弹出堆顶元素也就是最大元素
func (h *Heap) Pop() int {
if len(*h) <= 0 {
return -1
}
n := len(*h) - 1
//将堆顶元素和数组最后一个元素进行交换
h.swap(0, n)
//记录堆顶元素值
x := (*h)[n]
//删除最后一个元素,也就是最开始的堆顶元素
*h = (*h)[:len(*h)-1]
//新交换到堆顶的元素进行down操作
h.down(0)
return x
}