最小堆和最大堆 golang實現(xiàn)
二叉堆是一種特殊的堆圾浅,它滿足兩個性質:結構性和堆序性
- 結構性:二叉堆是一顆完全二叉樹崇决,完全二叉樹可以用一個數(shù)組表示捧韵,不需要指針互亮,所以效率更高。當用數(shù)組表示時坪蚁,數(shù)組中任一位置i上的元素奔穿,其左兒子在位置2i上,右兒子在位置(2i+ 1)上敏晤,其父節(jié)點在位置(i/2)上贱田。
- 堆序性質:堆的最小值或最大值在根節(jié)點上,所以可以快速找到最大值或最小值嘴脾。
最大堆和最小堆是二叉堆的兩種形式男摧。
-最大堆:根結點的鍵值是所有堆結點鍵值中最大者的堆。
-最小堆:根結點的鍵值是所有堆結點鍵值中最小者的堆译打。
1. 最小堆實現(xiàn)耗拓,不使用container/heap
type MinHeap struct {
Element []int
}
定義構造方法
數(shù)組中第一個元素不使用,存放一個小于堆中任何數(shù)字的值用于結束循環(huán)奏司。
// MinHeap構造方法
func NewMinHeap() *MinHeap {
// 第一個元素僅用于結束insert中的 for 循環(huán)
h := &MinHeap{Element: []int{math.MinInt64}}
return h
}
插入
插入元素就直接將元素增加到堆的末尾乔询,然后進行上浮操作,使二叉堆有序结澄。
如果上浮一直到根哥谷,時間復雜度為O(log N),但這種上浮操作一般結束的要早麻献。
// 插入數(shù)字,插入數(shù)字需要保證堆的性質
func (H *MinHeap) Insert(v int) {
H.Element = append(H.Element, v)
i := len(H.Element) - 1
// 上浮
for ; H.Element[i/2] > v; i /= 2 {
H.Element[i] = H.Element[i/2]
}
H.Element[i] = v
}
刪除最小值
刪除最大元素就直接從二叉堆頂端刪除们妥,然后進行下沉操作。最壞時間復雜度同樣為O(log N)
// 刪除并返回最小值
func (H *MinHeap) DeleteMin() (int, error) {
if len(H.Element) <= 1 {
return 0, fmt.Errorf("MinHeap is empty")
}
minElement := H.Element[1]
lastElement := H.Element[len(H.Element)-1]
var i, child int
for i = 1; i*2 < len(H.Element); i = child {
child = i * 2
if child < len(H.Element)-1 && H.Element[child+1] < H.Element[child] {
child ++
}
// 下濾一層
if lastElement > H.Element[child] {
H.Element[i] = H.Element[child]
} else {
break
}
}
H.Element[i] = lastElement
H.Element = H.Element[:len(H.Element)-1]
return minElement, nil
}
其他方法
// 堆的大小
func (H *MinHeap) Length() int {
return len(H.Element) - 1
}
// 獲取最小堆的最小值
func (H *MinHeap) Min() (int, error) {
if len(H.Element) > 1 {
return H.Element[1], nil
}
return 0, fmt.Errorf("heap is empty")
}
// MinHeap格式化輸出
func (H *MinHeap) String() string {
return fmt.Sprintf("%v", H.Element[1:])
}
2.下面介紹container/heap包 和最大堆的實現(xiàn)
heap源碼中定義了一個Interface 的接口勉吻,此接口一共包含五個方法监婶,我們定義一個實現(xiàn)此接口的類就實現(xiàn)了一個二叉堆
container/heap/heap.go
type Interface interface {
sort.Interface
Push(x interface{}) // add x as element Len()
Pop() interface{} // remove and return element Len() - 1.
}
sort.go
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)
}
定義一個最大堆,并實現(xiàn)heap.Interface 接口
type MaxHeap []int
func (h MaxHeap) Len() int {
return len(h)
}
func (h MaxHeap) Less(i, j int) bool {
// 由于是最大堆,所以使用大于號
return h[i] > h[j]
}
func (h *MaxHeap) Swap(i, j int) {
(*h)[i], (*h)[j] = (*h)[j], (*h)[i]
}
func (h *MaxHeap) Push(x interface{}) {
*h = append(*h, x.(int))
}
// Pop 彈出最后一個元素
func (h *MaxHeap) Pop() interface{}{
res := (*h)[len(*h)-1]
*h = (*h)[:len(*h)-1]
return res
}
測試最大堆
func main() {
h := make(MaxHeap, 0)
heap.Init(&h)
heap.Push(&h, 8)
heap.Push(&h, 1)
heap.Push(&h, 4)
heap.Push(&h, 5)
heap.Push(&h, 2)
fmt.Println(heap.Pop(&h))
fmt.Println(heap.Pop(&h))
fmt.Println(heap.Pop(&h))
fmt.Println(heap.Pop(&h))
fmt.Println(heap.Pop(&h))
}
>>>
8
5
4
2
1