我正在使用Package Heap中的IntHeap示例。对于minHEAP来说,每件事看起来都很简单。看一下如何获得最小值:我们只需要(*h)[0]
值。就像在堆说明中一样,根节点返回最小值
fmt.Printf("minimum: %d\n", (*h)[0]) // It will returns 1
奇怪的事情始于Pop()
方法。在这种情况下,最小值存储在数组的末尾。 x := old[n-1]
。但是上面的2行我从索引0得到了相同的最小值。
嗯...这很有趣。 Go代表Pop方法的反向数组如何发生? 想象以不同的方法排列数组的不同顺序是很奇怪的,而且是微小的,不常见的。
我在示例中添加了两行,是的,将反向数组传递给Pop方法:
fmt.Println("In Pop",*h) // In Pop [2 3 5 1]
fmt.Println("In Main",*h) // In Main [1 2 5 3]
这是一个完整的示例,其中有两个更改:
// This example demonstrates an integer heap built using the heap interface.
package main
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{} {
fmt.Println("In Pop",*h) // In Pop [2 3 5 1]
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])
fmt.Println("In Main",*h) // In Main [1 2 5 3]
for h.Len() > 0 {
fmt.Printf("%d ", heap.Pop(h))
}
}
和输出
minimum: 1
In Main [1 2 5 3]
In Pop [2 3 5 1]
1 In Pop [3 5 2]
2 In Pop [5 3]
3 In Pop [5]
5
答案 0 :(得分:2)
使用Init
从切片初始化堆时,它将通过重新排列切片来建立堆不变式。此操作为O(n)
,在初始化时仅发生一次,而不是在每次弹出时都发生!
然后,当您Pop
时,每个Pop
只需要O(log n)
。执行初始化对于确保我们可以弹出O(log n)
至关重要。
详细了解堆on Wikipedia。 article on Heapsort具有 heapify 操作的伪代码,该操作由heap.Init
)
Pop
的作用不可逆转。它:
[0]
处)与基础切片中的最后一个元素交换。现在最小元素在最后,元素[0]
在堆中的“错误”位置。down
原语将新元素[0]
移动到堆中的正确位置。这会重新整理堆中的某些元素-但这不是还原。[n-1]
,该元素从步骤1开始就是原始的最小元素。答案 1 :(得分:-1)
这是不可逆的。这是一种从MinHeap中删除最小元素的算法。
在当前情况下,程序包委派给开发人员步骤2。然后对除最后一个元素以外的所有堆执行步骤1和步骤3。