Golang標準庫學習—container/heap
container包中有三個資料結構:heap(堆)、list(連結串列)、ring(環)
Package heap
import "container/heap"
heap包提供了對任意實現了heap.Interface介面的型別的堆操作。最小堆是具有“每個節點都是以其為根的子樹中最小值”屬性的樹。最大堆相反。
樹的最小元素為其根元素,索引0的位置。最大堆相反。
heap是常用的實現優先佇列的方法。要建立一個優先佇列,實現一個具有使用(負的)優先順序作為比較的依據的Less方法的Heap介面,如此一來可用Push新增專案而用Pop取出佇列最高優先順序的專案。
type Interface
這裡不像list宣告型別,而是直接作為介面令外部使用
type Interface interface { sort.Interface Push(x interface{}) // add x as element Len() Pop() interface{} // remove and return element Len() - 1. }
任何實現了本介面的型別都可以用於構建最小堆。最小堆可以通過heap.Init建立,資料是遞增順序或者空的話也是最小堆。
其中,這個堆結構組合了sort.Interface,所以需要實現Len(), Less(), Swap()三個方法。
注意介面的Push和Pop方法是供heap包呼叫的,使用heap.Push和heap.Pop來向一個堆新增或者刪除元素。
heap對外提供五個方法
首先是Init方法。一個堆在使用任何堆操作之前應先初始化。Init函式對於堆的約束性是冪等的(多次執行無意義),並可能在任何時候堆的約束性被破壞時被呼叫。函式複雜度為O(n),其中n等於h.Len()。其中存在down內部方法,後面說。
func Init(h Interface) { // heapify n := h.Len() for i := n/2 - 1; i >= 0; i-- { down(h, i, n) } }
接著是向堆中新增元素的Push方法。向堆h中插入元素x,並保持堆的約束性。複雜度O(log(n)),其中n等於h.Len()。
func Push(h Interface, x interface{}) { h.Push(x) up(h, h.Len()-1) }
還有從堆中刪除根元素的Pop方法。刪除並返回堆h中的最小元素(不影響約束性)。複雜度O(log(n))。
func Pop(h Interface) interface{} { n := h.Len() - 1 h.Swap(0, n) down(h, 0, n) return h.Pop() }
然後是從堆中刪除第i各元素的Remov方法。刪除堆中的第i個元素,並保持堆的約束性。複雜度O(log(n))。
func Remove(h Interface, i int) interface{} { n := h.Len() - 1 if n != i { h.Swap(i, n) if !down(h, i, n) { up(h, i) } } return h.Pop() }
最後是調整堆的Fix方法。在修改第i個元素後,呼叫本函式修復堆,比刪除第i個元素後插入新元素更有效率。複雜度O(log(n))。
func Fix(h Interface, i int) { if !down(h, i, h.Len()) { up(h, i) } }
heap內部存在兩個方法來實現對外的五個方法
兩個方法分別實現堆的上下調整,單獨呼叫只能保證呼叫節點保持約束性,不能保證其它節點。
func up(h Interface, j int) { for { i := (j - 1) / 2 // parent if i == j || !h.Less(j, i) { break } h.Swap(i, j) j = i } } func down(h Interface, i0, n int) bool { i := i0 for { j1 := 2*i + 1 if j1 >= n || j1 < 0 { // j1 < 0 after int overflow break } j := j1 // left child if j2 := j1 + 1; j2 < n && h.Less(j2, j1) { j = j2 // = 2*i + 2 // right child } if !h.Less(j, i) { break } h.Swap(i, j) i = j } return i > i0 }
這裡不再做例項了,只要實現相應方法就可以使用堆了。好像golang裡也沒有像C++那樣做了priority_queue優先佇列的庫實現,用的時候自己做一個8。(標準庫裡好像有例子)
堆的用處包括使用頻率都還是很大的,具體的實現原理不再贅述,但還是要牢牢把握啊。
記錄每天解決的一點小問題,積累起來就能解決大問題。
相關文章
- C標準庫學習
- 6. 開篇《 刻意學習 Golang - 標準庫原始碼分析 》Golang原始碼
- golang標準庫之 fmtGolang
- golang標準庫的分析os包(6)Golang
- Go Web學習 -標準庫 net/http 使用GoWebHTTP
- go標準庫-log包原始碼學習Go原始碼
- Golang學習筆記 – 標準庫”net/http”的簡析及自制簡單路由框架Golang筆記HTTP路由框架
- Golang語言標準庫time實戰篇Golang
- 「Golang成長之路」標準庫之os包Golang
- 「Golang成長之路」標準庫之time包Golang
- C++學習筆記 — STL標準模板庫C++筆記
- 《C++ Primer》學習筆記(八):標準 IO 庫C++筆記
- 標準庫unsafe:帶你突破golang中的型別限制Golang型別
- Golang 標準庫 限流器 time/rate 設計與實現Golang
- C++標準庫、C++標準模版庫介紹C++
- log包在Golang語言的標準庫中是怎麼使用的?Golang
- 標準庫之template
- python常用標準庫Python
- Go標準庫ContextGoContext
- C++標準庫C++
- 深度學習煉丹-資料標準化深度學習
- 機器學習筆記——特徵標準化機器學習筆記特徵
- Golang 學習寶庫,各種資料收集Golang
- Golang 第三方庫學習 · xlsxGolang
- Golang 學習——陣列指標和指標陣列的區別Golang陣列指標
- C++標準庫:chronoC++
- C++標準庫:randomC++random
- PHP 標準庫 SplStack 棧PHP
- Python標準庫(待續)Python
- python標準庫目錄Python
- Linux程式設計學習筆記 | Linux IO學習[2] – 標準IOLinux程式設計筆記
- Go 的 golang.org/x/ 系列包和標準庫包有什麼區別?Golang
- Golang研學:在用好Golang指標型別Golang指標型別
- 標準庫之 random 模組random
- C 標準庫 – ctype.h
- 標準庫~JSON物件詳解JSON物件
- Python標準庫06 子程式Python
- go語言標準庫 - timeGo