Golang中heap包原始碼分析
阿新 • • 發佈:2018-11-02
heap的實現使用到了小根堆,下面先對堆做個簡單說明
1. 堆概念
堆是一種經過排序的完全二叉樹,其中任一非終端節點的資料值均不大於(或不小於)其左孩子和右孩子節點的值。
最大堆和最小堆是二叉堆的兩種形式。
最大堆:根結點的鍵值是所有堆結點鍵值中最大者。
最小堆:根結點的鍵值是所有堆結點鍵值中最小者。
2. heap
樹的最小元素在根部,為index 0.
heap包對任意實現了heap介面的型別提供堆操作。
heap是常用的實現優先佇列的方法。要建立一個優先佇列,實現一個具有使用(負的)優先順序作為比較的依據的Less方法的Heap介面,如此一來可用Push新增專案而用Pop取出佇列最高優先順序的專案。
heap需要實現的介面
// Any type that implements heap.Interface may be used as a // min-heap with the following invariants (established after // Init has been called or if the data is empty or sorted): // // !h.Less(j, i) for 0 <= i < h.Len() and 2*i+1 <= j <= 2*i+2 and j < h.Len() // // Note that Push and Pop in this interface are for package heap's // implementation to call. To add and remove things from the heap, // use heap.Push and heap.Pop. type Interface interface { sort.Interface Push(x interface{}) // add x as element Len() Pop() interface{} // remove and return element Len() - 1. }
// A type, typically a collection, that satisfies sort.Interface can be // sorted by the routines in this package. The methods require that the // elements of the collection be enumerated by an integer index. type Interface interface { // Len is the number of elements in the collection. Len() int // Less reports whether the element with // index i should sort before the element with index j. Less(i, j int) bool // Swap swaps the elements with indexes i and j. Swap(i, j int) }
其中sort.Interface用於排序,heap.Interface中Push和Pop方法分別用於插入和取出元素的操作
heap中的方法
func Fix(h Interface, i int) //在修改第i個元素後,呼叫本函式修復堆,比刪除第i個元素後插入新元素更有效率。複雜度O(log(n)),其中n等於h.Len()。
func Init(h Interface) //初始化一個堆。一個堆在使用任何堆操作之前應先初始化。Init函式對於堆的約束性是冪等的(多次執行無意義),並可能在任何時候堆的約束性被破壞時被呼叫。本函式複雜度為O(n),其中n等於h.Len()。
func Pop(h Interface) interface{} //刪除並返回堆h中的最小元素(不影響約束性)。複雜度O(log(n)),其中n等於h.Len()。該函式等價於Remove(h, 0)。
func Push(h Interface, x interface{}) //向堆h中插入元素x,並保持堆的約束性。複雜度O(log(n)),其中n等於h.Len()。
func Remove(h Interface, i int) interface{} //刪除堆中的第i個元素,並保持堆的約束性。複雜度O(log(n)),其中n等於h.Len()。
4.示例
(1) 儲存int型別元素的heap實現
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{}) {
if v,ok := x.(int); ok {
*h = append(*h,v)
}
}
func (h *intHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
//測試
func main() {
h := &intHeap{5,7,9,2}
heap.Init(h)
heap.Push(h,3)
fmt.Println((*h)[0])
for h.Len() > 0 {
fmt.Printf("%d ", heap.Pop(h))
}
}
執行結果:(取出的元素是從小到大)
2
2 3 5 7 9
(2) 實現heap的優先佇列(以下程式碼摘自nsq)
type Item struct {
Value interface{}
Priority int64 //優先順序
Index int
}
// this is a priority queue as implemented by a min heap
// ie. the 0th element is the *lowest* value
//PriorityQueue實現了heap介面
type PriorityQueue []*Item
func New(capacity int) PriorityQueue {
return make(PriorityQueue, 0, capacity)
}
/*
Len(),Less()和Swap用於按Priority排序
*/
func (pq PriorityQueue) Len() int {
return len(pq)
}
func (pq PriorityQueue) Less(i, j int) bool {
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)
c := cap(*pq)
if n+1 > c { //擴容
npq := make(PriorityQueue, n, c*2)
copy(npq, *pq)
*pq = npq
}
*pq = (*pq)[0 : n+1]
item := x.(*Item)
item.Index = n
(*pq)[n] = item
}
func (pq *PriorityQueue) Pop() interface{} {
n := len(*pq)
c := cap(*pq)
if n < (c/2) && c > 25 {//縮容
npq := make(PriorityQueue, n, c/2)
copy(npq, *pq)
*pq = npq
}
item := (*pq)[n-1]
item.Index = -1
*pq = (*pq)[0 : n-1]
return item
}
func main() {
item1 := &Item{
Value : "aaaa",
Priority : 5,
}
item2 := &Item{
Value : "bbbb",
Priority : 2,
}
item3 := &Item{
Value : "cccc",
Priority : 10,
}
item4 := &Item{
Value : "dddd",
Priority : 1,
}
pq := New(100)
heap.Push(&pq,item1)
heap.Push(&pq,item2)
heap.Push(&pq,item3)
heap.Push(&pq,item4)
for pq.Len() > 0 {
fmt.Println(heap.Pop(&pq))
}
}
執行結果:
&{dddd 1 -1}
&{bbbb 2 -1}
&{aaaa 5 -1}
&{cccc 10 -1}
參考地址:https://www.cnblogs.com/davygeek/p/5916230.html