容器数据结构heap | container/heap
Package heap
import "container/heap"
- 概述
- 索引
- 例子
概述
Heap 包为任何实现 heap.Interface 的类型提供堆操作。堆是具有属性的树,每个节点是其子树中的最小值节点。
树中的最小元素是参数为0的根。
堆是实现优先级队列的常用方式。要构建一个优先级队列,请将具有(负)优先级的 Heap 接口作为 Less 方法的排序来执行,因此推送会添加项目,而Pop 将从队列中移除最高优先级的项目。这些例子包括这样的实现;文件example_pq_test.go 具有完整的源代码。
示例 (IntHeap)
本示例将几个 int 插入到 IntHeap 中,检查最小值,并按优先级顺序删除它们。
// 本示例演示了使用堆接口构建的整数堆。
package main
import (
"container/heap"
"fmt"
)
// IntHeap是一个整型的整数。
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和Pop使用指针接收器,因为它们修改切片的长度,
// 不仅仅是其内容。
*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
}
// 本示例将几个int插入到IntHeap中,检查最小值,
// 并按优先顺序删除它们。
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("%d ", heap.Pop(h))
}
}
示例 (PriorityQueue)
本示例使用某些项目创建 PriorityQueue,添加并操作项目,然后按优先级顺序删除项目。
// 此示例演示使用堆接口构建的优先级队列。
package main
import (
"container/heap"
"fmt"
)
// item是我们在优先队列中管理的item。
type Item struct {
value string // item的值;任意取值。
priority int // 队列中项目的优先级。
// 该参数是更新所需的,由heap.Interface方法维护。
index int // 堆中项目的参数。
}
// PriorityQueue实现堆。接口并保存项目。
type PriorityQueue []*Item
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool {
// 我们希望Pop给我们最高的优先权,而不是最低的优先权,所以我们使用的比这里更大。
return pq[i].priority > pq[j].priority
}
func (pq PriorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
pq[i].index = i
pq[j].index = j
}
func (pq *PriorityQueue) Push(x interface{}) {
n := len(*pq)
item := x.(*Item)
item.index = n
*pq = append(*pq, item)
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
item.index = -1 // for safety
*pq = old[0 : n-1]
return item
}
// 更新修改队列中某个项目的优先级和值。
func (pq *PriorityQueue) update(item *Item, value string, priority int) {
item.value = value
item.priority = priority
heap.Fix(pq, item.index)
}
// 本示例使用某些项目创建PriorityQueue,添加和操作项目,
// 然后按优先顺序删除这些项目。
func main() {
// 一些项目和它们的优先级。
items := map[string]int{
"banana": 3, "apple": 2, "pear": 4,
}
// 创建一个优先级队列,将其中的项目,和
// 建立优先队列(堆)不变量。
pq := make(PriorityQueue, len(items))
i := 0
for value, priority := range items {
pq[i] = &Item{
value: value,
priority: priority,
index: i,
}
i++
}
heap.Init(&pq)
// 插入一个新项目,然后修改其优先级。
item := &Item{
value: "orange",
priority: 1,
}
heap.Push(&pq, item)
pq.update(item, item.value, 5)
// 取出项目;以优先顺序递减排列。
for pq.Len() > 0 {
item := heap.Pop(&pq).(*Item)
fmt.Printf("%.2d:%s ", item.priority, item.value)
}
}
索引
- func Fix(h Interface, i int)
- func Init(h Interface)
- func Pop(h Interface) interface{}
- func Push(h Interface, x interface{})
- func Remove(h Interface, i int) interface{}
- type Interface
示例
Package (IntHeap) Package (PriorityQueue)
包文件
func Fix(查看源代码)
func Fix(h Interface, i int)
Fix 在索引 i 处的元素已更改其值后重新建立堆排序。更改索引为 i 的元素的值,然后调用 Fix 相当于调用 Remove(h, i),然后再调用新值的代价。复杂度为 O(log(n)),其中 n = h.Len()。
func Init(查看源代码)
func Init(h Interface)
必须在使用任何堆操作之前初始化堆。Init 对于堆不变式是幂等的,当堆不变量可能已经失效时可以调用Init。它的复杂性是 O(n),其中n = h.Len()。
func Pop(查看源代码)
func Pop(h Interface) interface{}
Pop 从堆中删除最小元素(根据Less)并返回。复杂度为 O(log(n)),其中 n = h.Len()。它相当于 Remove(h, 0)。
func Push(查看源代码)
func Push(h Interface, x interface{})
推动元素 x 到堆上。复杂度为 O(log(n)),其中 n = h.Len()。
func Remove(查看源代码)
func Remove(h Interface, i int) interface{}
从堆中删除参数 i 处的元素。复杂度为 O(log(n)),其中 n = h.Len()。
type Interface(查看源代码)
任何实现堆的类型 .Interface 可用作具有以下不变式的最小堆(在调用 Init 之后或数据为空或排序后建立):
!h.Less(j, i) for 0 <= i < h.Len() and 2*i+1 <= j <= 2*i+2 and j < h.Len()
请注意,此接口中的 Push 和 Pop 用于调用包堆的实现。要从堆中添加和删除东西,请使用 heap.Push 和 heap.Pop。
type Interface interface {
sort.Interface
Push(x interface{}) // 将x添加为元素Len()
Pop() interface{} // 删除并返回元素Len()-1.
}