github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/container/heap/example_pq_test.go (about)

     1  // Copyright 2012 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // This example demonstrates a priority queue built using the heap interface.
     6  // 通过堆接口 实现优先级队列的示例
     7  package heap_test
     8  
     9  import (
    10  	"container/heap"
    11  	"fmt"
    12  )
    13  
    14  // An Item is something we manage in a priority queue.
    15  // 优先级队列中的数据项Item
    16  type Item struct {
    17  	value    string // The value of the item; arbitrary.
    18  	priority int    // The priority of the item in the queue.
    19  	// The index is needed by update and is maintained by the heap.Interface methods.
    20  	index int // The index of the item in the heap. // Item 在heap中的索引
    21  }
    22  
    23  // A PriorityQueue implements heap.Interface and holds Items.
    24  // 优先级队列
    25  type PriorityQueue []*Item
    26  
    27  func (pq PriorityQueue) Len() int { return len(pq) }
    28  
    29  func (pq PriorityQueue) Less(i, j int) bool {
    30  	// We want Pop to give us the highest, not lowest, priority so we use greater than here.
    31  	// 需要返回最大的优先级, 所以这里使用>
    32  	return pq[i].priority > pq[j].priority
    33  }
    34  
    35  func (pq PriorityQueue) Swap(i, j int) {
    36  	pq[i], pq[j] = pq[j], pq[i]
    37  	pq[i].index = i // 保存数组索引
    38  	pq[j].index = j
    39  }
    40  
    41  func (pq *PriorityQueue) Push(x interface{}) {
    42  	n := len(*pq)
    43  	item := x.(*Item)
    44  	item.index = n // 保存数组索引
    45  	*pq = append(*pq, item)
    46  }
    47  
    48  func (pq *PriorityQueue) Pop() interface{} {
    49  	old := *pq
    50  	n := len(old)
    51  	item := old[n-1]
    52  	old[n-1] = nil  // avoid memory leak // 手动赋值为Nil, 避免内存泄露
    53  	item.index = -1 // for safety //设置索引为-1
    54  	*pq = old[0 : n-1]
    55  	return item
    56  }
    57  
    58  // update modifies the priority and value of an Item in the queue.
    59  // 修改优先级队列项的优先级和值,并且调整最小堆(因为返回优先级高的项, 应该算是最大堆)
    60  func (pq *PriorityQueue) update(item *Item, value string, priority int) {
    61  	item.value = value
    62  	item.priority = priority
    63  	heap.Fix(pq, item.index)
    64  }
    65  
    66  // This example creates a PriorityQueue with some items, adds and manipulates an item,
    67  // and then removes the items in priority order.
    68  func Example_priorityQueue() {
    69  	// Some items and their priorities.
    70  	items := map[string]int{
    71  		"banana": 3, "apple": 2, "pear": 4,
    72  	}
    73  
    74  	// Create a priority queue, put the items in it, and
    75  	// establish the priority queue (heap) invariants.
    76  	pq := make(PriorityQueue, len(items))
    77  	i := 0
    78  	for value, priority := range items {
    79  		pq[i] = &Item{
    80  			value:    value,
    81  			priority: priority,
    82  			index:    i,
    83  		}
    84  		i++
    85  	}
    86  	heap.Init(&pq) // 队列构建堆化
    87  
    88  	// Insert a new item and then modify its priority.
    89  	item := &Item{
    90  		value:    "orange",
    91  		priority: 1,
    92  	}
    93  	heap.Push(&pq, item)           // 插入一个新的堆
    94  	pq.update(item, item.value, 5) // 修改这个item的优先级为5
    95  
    96  	// Take the items out; they arrive in decreasing priority order.
    97  	// 降序的优先级次序
    98  	for pq.Len() > 0 {
    99  		item := heap.Pop(&pq).(*Item)
   100  		fmt.Printf("%.2d:%s ", item.priority, item.value)
   101  	}
   102  	// Output:
   103  	// 05:orange 04:pear 03:banana 02:apple
   104  }