Go 語言中如何使用堆 Heap

Go 提供了 container/heap 這個包來實現(xiàn)堆的操作。堆實際上是一個樹的結(jié)構(gòu),每個元素的值都是它的子樹中最小的,因此根節(jié)點 index = 0 的值是最小的,即最小堆。

堆也是實現(xiàn)優(yōu)先隊列 Priority Queue 的常用方式。

堆中元素的類型需要實現(xiàn) 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(), Less, Swap 方法:

一個完整的示例如下:
注意注釋中的一句話 Push 和 Pop 方法需要使用指針,因為它們會修改 slice 的長度,而不僅僅只內(nèi)容

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
    }
}

Leetcode 692. Top K Frequent Words 也可以使用 Go 語言通過構(gòu)造 PriorityQueue 來實現(xiàn):

type Item struct {
    word  string
    count int
}

type ItemHeap []Item

func (h ItemHeap) Len() int { return len(h) }

func (h ItemHeap) Less(i, j int) bool {
    if h[i].count != h[j].count {
        return h[i].count < h[j].count
    } else {
        return h[i].word > h[j].word
    }
}

func (h ItemHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }

func (h *ItemHeap) Push(val interface{}) {
    *h = append(*h, val.(Item))
}

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

func topKFrequent(words []string, k int) []string {
    countMap := make(map[string]int)
    for _, word := range words {
        countMap[word]++
    }

    h := &ItemHeap{}
    for w, v := range countMap {
        heap.Push(h, Item{
            word:  w,
            count: v,
        })

        if h.Len() > k {
            heap.Pop(h)
        }
    }

    res := make([]string, h.Len())
    for i := h.Len() - 1; i >= 0; i-- {
        item := heap.Pop(h).(Item)
        res[i] = item.word
    }
    return res
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容