堆索引示例说明
Explanation of heap indexing example
此代码取自 Go 堆示例(带有我自己添加的打印件)。这里是游乐场。
https://play.golang.org/p/E69SfBIZF5X
大多数事情都很简单明了,但我无法解决的一件事是为什么 'minimum' 在 main()
[=30] 堆的 index 0
上打印=] 值 1
(正确的最小值)但在堆的弹出函数中打印 4 returns 1
(见输出)。
如果堆的根(最小值)总是在 n=0
,为什么它在 pop 函数本身中是 n=4
?然后它似乎工作正常,按降序排列。
有人可以解释一下这是怎么回事吗?在我了解发生了什么之前,我不太愿意实施像 Pop 这样的东西。
// 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{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
fmt.Printf("n: %v\n", n)
fmt.Printf("x: %v\n", x)
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])
for h.Len() > 0 {
fmt.Printf("roll: %d\n", (*h)[0])
fmt.Printf("%d\n", heap.Pop(h))
}
}
-
Output
x = value
n = index
minimum: 1
roll: 1
n: 4
x: 1
1
roll: 2
n: 3
x: 2
2
roll: 3
n: 2
x: 3
3
roll: 5
n: 1
x: 5
5
如果您知道整个堆结构是正确的(a[n] < a[2*n+1] && a[n] < a[2*n+2]
,对于边界内的所有 n
),教科书堆算法包括一种修复堆的方法,除了根是错误的, 在 O(lg n) 时间内。当你 heap.Pop()
一个项目时,它几乎肯定是 (*IntHeap).Swap
的第一个和最后一个元素,进行更多的交换以维护堆不变量,然后 (*IntHeap).Pop
是 最后一个 元素。这就是您在这里看到的。
您也可以使用它来实现 heap sort。假设您有一个要排序的数组 int[4]
。取一片s int[] = (a, len=4, cap=4)
,然后:
- 如果
len(s) == 1
,停止。
- 交换
s[0]
和 s[len(s)-1]
。
- 将切片缩小一项:
s = (array(s), len=len(s)-1, cap=cap(s))
。
- 如果堆出现问题,请修复它。
- 转到 1。
假设您的示例以 [1, 2, 5, 3] 开头。那么:
[1, 2, 5, 3]
[3, 2, 5, 1] Swap first and last
[3, 2, 5], 1 Shrink slice by one
[2, 3, 5], 1 Correct heap invariant
[5, 3, 2], 1 Swap first and last
[5, 3], 2, 1 Shrink slice by one
[3, 5], 2, 1 Correct heap invariant
[5, 3], 2, 1 Swap first and last
[5], 3, 2, 1 Shrink slice by one
5, 3, 2, 1 Sorted (descending order)
此代码取自 Go 堆示例(带有我自己添加的打印件)。这里是游乐场。 https://play.golang.org/p/E69SfBIZF5X
大多数事情都很简单明了,但我无法解决的一件事是为什么 'minimum' 在 main()
[=30] 堆的 index 0
上打印=] 值 1
(正确的最小值)但在堆的弹出函数中打印 4 returns 1
(见输出)。
如果堆的根(最小值)总是在 n=0
,为什么它在 pop 函数本身中是 n=4
?然后它似乎工作正常,按降序排列。
有人可以解释一下这是怎么回事吗?在我了解发生了什么之前,我不太愿意实施像 Pop 这样的东西。
// 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{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
fmt.Printf("n: %v\n", n)
fmt.Printf("x: %v\n", x)
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])
for h.Len() > 0 {
fmt.Printf("roll: %d\n", (*h)[0])
fmt.Printf("%d\n", heap.Pop(h))
}
}
-
Output
x = value
n = index
minimum: 1
roll: 1
n: 4
x: 1
1
roll: 2
n: 3
x: 2
2
roll: 3
n: 2
x: 3
3
roll: 5
n: 1
x: 5
5
如果您知道整个堆结构是正确的(a[n] < a[2*n+1] && a[n] < a[2*n+2]
,对于边界内的所有 n
),教科书堆算法包括一种修复堆的方法,除了根是错误的, 在 O(lg n) 时间内。当你 heap.Pop()
一个项目时,它几乎肯定是 (*IntHeap).Swap
的第一个和最后一个元素,进行更多的交换以维护堆不变量,然后 (*IntHeap).Pop
是 最后一个 元素。这就是您在这里看到的。
您也可以使用它来实现 heap sort。假设您有一个要排序的数组 int[4]
。取一片s int[] = (a, len=4, cap=4)
,然后:
- 如果
len(s) == 1
,停止。 - 交换
s[0]
和s[len(s)-1]
。 - 将切片缩小一项:
s = (array(s), len=len(s)-1, cap=cap(s))
。 - 如果堆出现问题,请修复它。
- 转到 1。
假设您的示例以 [1, 2, 5, 3] 开头。那么:
[1, 2, 5, 3]
[3, 2, 5, 1] Swap first and last
[3, 2, 5], 1 Shrink slice by one
[2, 3, 5], 1 Correct heap invariant
[5, 3, 2], 1 Swap first and last
[5, 3], 2, 1 Shrink slice by one
[3, 5], 2, 1 Correct heap invariant
[5, 3], 2, 1 Swap first and last
[5], 3, 2, 1 Shrink slice by one
5, 3, 2, 1 Sorted (descending order)