Go 语言中实现优先队列,最大堆和最小堆通常可以通过使用容器/heap包来完成。Go 语言的heap包提供了一个堆操作的接口,它允许用户实现任意类型的堆,包括最大堆和最小堆。
1. 优先队列 优先队列是一种特殊的队列,元素出队顺序是根据优先级来决定的,而不是按照元素入队顺序。在Go语言中,优先队列可以通过heap包来实现。
2. 最大堆 最大堆是一种特殊的完全二叉树,其中每个父节点的值都大于或等于其子节点的值。在Go语言中,可以通过实现heap.Interface接口来创建最大堆。
3. 最小堆 最小堆与最大堆相反,其中每个父节点的值都小于或等于其子节点的值。最小堆也可以通过实现heap.Interface接口来创建。
实现步骤 定义堆的元素类型 首先,你需要定义一个元素类型,这个类型将用于存储在堆中的元素。
实现heap.Interface接口 要使用heap包的功能,你需要实现heap.Interface接口。这个接口包括三个方法:Push, Pop, 和 Less。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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 {}) { *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 }
使用heap.Init初始化堆 在使用堆之前,你需要调用heap.Init来初始化它。
1 2 3 var h IntHeap heap.Init(&h)
添加元素 使用heap.Push来添加元素。
1 2 heap.Push(&h, 10 ) heap.Push(&&h, 20 )
移除元素 使用heap.Pop来移除并获取堆顶元素。
1 2 top := heap.Pop(&h) fmt.Printf("top element: %v\n" , top)
修改元素 如果你需要修改堆中的元素,你需要自己处理,因为heap包不提供修改元素的接口。
转换为最大堆 如果你需要实现最大堆,只需要修改Less方法,让它返回父节点大于子节点。
1 func (h IntHeap) Less(i, j int ) bool { return h[i] > h[j] }
以上就是在Go语言中实现优先队列,最大堆和最小堆的基本步骤。通过实现heap.Interface接口,可以轻松地创建和管理各种类型的堆。
例题 215. 数组中的第K个最大元素 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package leetcode215import "container/heap" func findKthLargest (nums []int , k int ) int { h := heapify(nums) var res any for i := 0 ; i < k; i++ { res = heap.Pop(&h) } return res.(int ) }type BigHeap []int func (h BigHeap) Len() int { return len (h) }func (h BigHeap) Less(i, j int ) bool { return h[i] > h[j] }func (h BigHeap) Swap(i, j int ) { tmp := h[i] h[i] = h[j] h[j] = tmp }func (h *BigHeap) Push(x any) { *h = append (*h, x.(int )) }func (h *BigHeap) Pop() any { x := (*h)[h.Len()-1 ] *h = (*h)[:h.Len()-1 ] return x }func heapify (nums []int ) BigHeap { h := BigHeap(nums) h := make (BigHeap, len (nums)) copy (h, nums) heap.Init(&h) return h }
涉及到两个元素,先构建一个长度为2的数组,然后对其value 进行优先队列的排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 func topKFrequent (nums []int , k int ) []int { map_num:=map [int ]int {} for _,item:=range nums{ map_num[item]++ } h:=&IHeap{} heap.Init(h) for key,value:=range map_num{ heap.Push(h,[2 ]int {key,value}) if h.Len()>k{ heap.Pop(h) } } res:=make ([]int ,k) for i:=0 ;i<k;i++{ res[k-i-1 ]=heap.Pop(h).([2 ]int )[0 ] } return res }type IHeap [][2 ]int func (h IHeap) Len()int { return len (h) }func (h IHeap) Less (i,j int ) bool { return h[i][1 ]<h[j][1 ] }func (h IHeap) Swap(i,j int ) { h[i],h[j]=h[j],h[i] }func (h *IHeap) Push(x interface {}){ *h=append (*h,x.([2 ]int )) }func (h *IHeap) Pop() interface {}{ old:=*h n:=len (old) x:=old[n-1 ] *h=old[0 :n-1 ] return x }