小顶堆

21 阅读1分钟

Go 提供了 container/heap 这个包来实现堆的操作。堆实际上是一个树的结构,每个元素的值都是它的子树中最小的,因此根节点 index = 0 的值是最小的,即最小堆。

堆也是实现优先队列 Priority Queue 的常用方式。

堆中元素的类型需要实现 heap.Interface 这个接口:

type Interface interface {
    sort.Interface
    Push(x interface{}) // add x as element Len()
    Pop() interface{}   // remove and return element Len() - 1.
}

其中 sort.Interface 包括 Len()LessSwap 方法:

一个完整的示例如下:
注意注释中的一句话 Push 和 Pop 方法需要使用指针,因为它们会修改 slice 的长度,而不仅仅只内容

import (
    "container/heap"
    "fmt"
)

// An IntHeap is a min-heap of ints.
type IntHeap []int

func (h IntHeap) Len() int           { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] < h[j] }
func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *IntHeap) Push(x interface{}) {
    // Push and Pop use pointer receivers because they modify the slice's length,
    // not just its contents.
    *h = append(*h, x.(int))
}

func (h *IntHeap) Pop() interface{} {
    old := *h
    n := len(old)
    x := old[n-1]
    *h = old[0 : n-1]
    return x
}

// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func main() {
    h := &IntHeap{2, 1, 5}
    heap.Init(h)
    heap.Push(h, 3)
    fmt.Printf("minimum: %d\n", (*h)[0]) // minimum: 1
    for h.Len() > 0 {
        fmt.Printf("%d ", heap.Pop(h)) // 1 2 3 5
    }
}