|
| 1 | +package heap_test |
| 2 | + |
| 3 | +import ( |
| 4 | + "container/heap" |
| 5 | + "fmt" |
| 6 | + "testing" |
| 7 | +) |
| 8 | + |
| 9 | +type myHeap []int |
| 10 | + |
| 11 | +func (h *myHeap) Less(i, j int) bool { |
| 12 | + return (*h)[i] < (*h)[j] |
| 13 | +} |
| 14 | + |
| 15 | +func (h *myHeap) Swap(i, j int) { |
| 16 | + (*h)[i], (*h)[j] = (*h)[j], (*h)[i] |
| 17 | +} |
| 18 | + |
| 19 | +func (h *myHeap) Len() int { |
| 20 | + return len(*h) |
| 21 | +} |
| 22 | + |
| 23 | +func (h *myHeap) Pop() (v interface{}) { |
| 24 | + *h, v = (*h)[:h.Len()-1], (*h)[h.Len()-1] |
| 25 | + return |
| 26 | +} |
| 27 | + |
| 28 | +func (h *myHeap) Push(v interface{}) { |
| 29 | + *h = append(*h, v.(int)) |
| 30 | +} |
| 31 | + |
| 32 | +func TestHeap(t *testing.T) { |
| 33 | + h := new(myHeap) |
| 34 | + |
| 35 | + for i := 20; i > 10; i-- { |
| 36 | + h.Push(i) |
| 37 | + } |
| 38 | + heap.Init(h) |
| 39 | + |
| 40 | + for i := 10; i > 0; i-- { |
| 41 | + heap.Push(h, i) |
| 42 | + } |
| 43 | + |
| 44 | + for i := 1; h.Len() > 0; i++ { |
| 45 | + x := heap.Pop(h).(int) |
| 46 | + if i < 20 { |
| 47 | + heap.Push(h, 20+i) |
| 48 | + } |
| 49 | + fmt.Println(x) |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +// An Item is something we manage in a priority queue. |
| 54 | +type Item struct { |
| 55 | + value string // The value of the item; arbitrary. |
| 56 | + priority int // The priority of the item in the queue. |
| 57 | + // The index is needed by update and is maintained by the heap.Interface methods. |
| 58 | + index int // The index of the item in the heap. |
| 59 | +} |
| 60 | + |
| 61 | +// A PriorityQueue implements heap.Interface and holds Items. |
| 62 | +type PriorityQueue []*Item |
| 63 | + |
| 64 | +func (pq PriorityQueue) Len() int { return len(pq) } |
| 65 | + |
| 66 | +func (pq PriorityQueue) Less(i, j int) bool { |
| 67 | + // We want Pop to give us the highest, not lowest, priority so we use greater than here. |
| 68 | + return pq[i].priority > pq[j].priority |
| 69 | +} |
| 70 | + |
| 71 | +func (pq PriorityQueue) Swap(i, j int) { |
| 72 | + pq[i], pq[j] = pq[j], pq[i] |
| 73 | + pq[i].index = i |
| 74 | + pq[j].index = j |
| 75 | +} |
| 76 | + |
| 77 | +func (pq *PriorityQueue) Push(x interface{}) { |
| 78 | + n := len(*pq) |
| 79 | + item := x.(*Item) |
| 80 | + item.index = n |
| 81 | + *pq = append(*pq, item) |
| 82 | +} |
| 83 | + |
| 84 | +func (pq *PriorityQueue) Pop() interface{} { |
| 85 | + old := *pq |
| 86 | + n := len(old) |
| 87 | + item := old[n-1] |
| 88 | + old[n-1] = nil // avoid memory leak |
| 89 | + item.index = -1 // for safety |
| 90 | + *pq = old[0 : n-1] |
| 91 | + return item |
| 92 | +} |
| 93 | + |
| 94 | +// update modifies the priority and value of an Item in the queue. |
| 95 | +func (pq *PriorityQueue) update(item *Item, value string, priority int) { |
| 96 | + item.value = value |
| 97 | + item.priority = priority |
| 98 | + heap.Fix(pq, item.index) |
| 99 | +} |
| 100 | + |
| 101 | +// This example creates a PriorityQueue with some items, adds and manipulates an item, |
| 102 | +// and then removes the items in priority order. |
| 103 | +func Example_priorityQueue() { |
| 104 | + // Some items and their priorities. |
| 105 | + items := map[string]int{ |
| 106 | + "banana": 3, "apple": 2, "pear": 4, |
| 107 | + } |
| 108 | + |
| 109 | + // Create a priority queue, put the items in it, and |
| 110 | + // establish the priority queue (heap) invariants. |
| 111 | + pq := make(PriorityQueue, len(items)) |
| 112 | + i := 0 |
| 113 | + for value, priority := range items { |
| 114 | + pq[i] = &Item{ |
| 115 | + value: value, |
| 116 | + priority: priority, |
| 117 | + index: i, |
| 118 | + } |
| 119 | + i++ |
| 120 | + } |
| 121 | + heap.Init(&pq) |
| 122 | + |
| 123 | + // Insert a new item and then modify its priority. |
| 124 | + item := &Item{ |
| 125 | + value: "orange", |
| 126 | + priority: 1, |
| 127 | + } |
| 128 | + heap.Push(&pq, item) |
| 129 | + pq.update(item, item.value, 5) |
| 130 | + |
| 131 | + // Take the items out; they arrive in decreasing priority order. |
| 132 | + for pq.Len() > 0 { |
| 133 | + item := heap.Pop(&pq).(*Item) |
| 134 | + fmt.Printf("%.2d:%s ", item.priority, item.value) |
| 135 | + } |
| 136 | + // Output: |
| 137 | + // 05:orange 04:pear 03:banana 02:apple |
| 138 | +} |
0 commit comments