SDK中heap包中的接口,任何实现该接口的类型都可以作为堆
type Interface interface {
sort.Interface
Push(x interface{}) // add x as element Len()
Pop() interface{} // remove and return element Len() - 1.
}
自定义myHeap堆
//自定以堆
type myHeap []int
//实现heap接口
//1.实现sort包中的接口
func (h myHeap) Len() int { return len(h) }
func (h myHeap) Less(i, j int) bool { return h[i] < h[j] } //小于号改变为大于号,变成大根堆
func (h myHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
//2.实现另外的两个方法
func (h *myHeap) Push(x interface{}) {
fmt.Print("Push()被调用了:")
*h = append(*h, x.(int))
}
func (h *myHeap) Pop() interface{} {
fmt.Print("Pop()被调用了:")
a := *h
v := a[len(a)-1]
*h = a[:len(a)-1] //切片长度减一
return v
}
func Example_myHeap() {
h := &myHeap{2, 1, 5}
heap.Init(h)//对该类型进行初始化,相当于对切片重新修改为堆排序的状态。
//注意:初始化之后堆就产生了
fmt.Println(*h) //[5 1 2]
heap.Push(h, 3) //调用heap包中提供的函数Init()、Push(),Pop(),就可以对我们的类型进行取堆顶,往堆中添加元素了
fmt.Printf("minimum: %d\n", (*h)[0])
for h.Len() > 0 {
fmt.Printf("%d ", heap.Pop(h))
}
// Output:
// minimum: 1
// 1 2 3 5
}
func main() {
Example_myHeap()
/*
Push()被调用了:minimum: 1
Pop()被调用了:1 Pop()被调用了:2 Pop()被调用了:3 Pop()被调用了:5
*/
}
再看一个栗子
这个是力扣上的一到需要用堆的算法题,我们可以直接使用上面的方法实现一个KthLargest类型的堆。
//结构体类型的堆
type KthLargest struct {
sort.IntSlice
//这个是sort包中的一个类型:type IntSlice []int,该类型实现了heap包中的sort.Interface接口。
//可能是继承的关系,因此结构体也就不用实现sort包中的接口,我们只用实现另外的两个方法Pop(),Push()。
k int
}
func Constructor(k int, nums []int) KthLargest {
kl := KthLargest{k: k}
for _, val := range nums {
kl.Add(val)
}
return kl
}
func (kl *KthLargest) Push(v interface{}) {
kl.IntSlice = append(kl.IntSlice, v.(int))
}
func (kl *KthLargest) Pop() interface{} {
a := kl.IntSlice
v := a[len(a)-1]
kl.IntSlice = a[:len(a)-1]
return v
}
func (kl *KthLargest) Add(val int) int {
if (kl.myHeap).Len() >= kl.k {
if val > kl.myHeap[0]{
heap.Pop(&kl.myHeap)
heap.Push(&kl.myHeap, val)
}
}else{
heap.Push(&kl.myHeap, val)
}
//返回k个中最小的那个,也就是第k大的那个,因为k个元素是按照小根堆排序的,因此取出来堆顶就是我们最小的那个了,栈顶也就是切片的第一个元素
return kl.myHeap[0]
}