-
Notifications
You must be signed in to change notification settings - Fork 140
/
minheap.go
95 lines (87 loc) · 2.79 KB
/
minheap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package minheap
import (
"fmt"
"ultimate-go/algorithms/data-structures/heap"
)
/*
* the largest is on the top
* parent is big then child
* root : i = 0
* parent(i): (i-1)/2
* left(i): 2*i + 1
* right(i): 2*i + 2
* 2^n , n 为level, 2^n为最小size
BuildMinHeap, 创建MinHeap
MinHeapifyUp, 向上对比,传入childIndex, 递归与parent对比,大的做parent
MinHeapifyDown, 向下对比,传入parentIndex, 递归与left and right child对比,大的做parent
Insert(item int), 添加,append到最后,因为新增child所有需要MinHeapifyUp
ExtractMin() int, 删除root, 删除前先与last交换,最后删除lastItem, 因为root变了, 所有需要MinHeapifyDown
HeapSort(), 排序
*/
type MinHeap struct {
*heap.Heap
}
func BuildMinHeap(arr []int) MinHeap {
h := MinHeap{&heap.Heap{Items: arr, HeapSize: len(arr)}}
// len(arr) / 2, 即从倒数第二层开始heapify, 除于2是为了减少heapify,从最下面的node开始往上比较
for i := len(arr) / 2; i >= 0; i-- {
// i 与 i的left and right child对比
h.MinHeapifyDown(i)
}
return h
}
// 向下对比,传入parentIndex, 递归与left and right child对比,小的做parent
func (h *MinHeap) MinHeapifyDown(parentIndex int) {
l, r := h.GetLeftChildIndex(parentIndex), h.GetRightChildIndex(parentIndex)
min := parentIndex
if l < h.HeapSize && h.Items[l] < h.Items[min] {
min = l
}
if r < h.HeapSize && h.Items[r] < h.Items[min] {
min = r
}
if min != parentIndex {
h.Items[parentIndex], h.Items[min] = h.Items[min], h.Items[parentIndex]
h.MinHeapifyDown(min)
}
}
// 向上对比,传入childIndex, 递归与parent对比,小的做parent
func (h *MinHeap) MinHeapifyUp(childIndex int) {
parentIndex := h.GetParentIndex(childIndex)
if parentIndex >= 0 && h.Items[childIndex] < h.Items[parentIndex] {
h.Items[childIndex], h.Items[parentIndex] = h.Items[parentIndex], h.Items[childIndex]
h.MinHeapifyUp(parentIndex)
}
}
func (h *MinHeap) Insert(item int) {
h.Items = append(h.Items, item)
h.HeapSize++
h.MinHeapifyUp(h.HeapSize - 1)
}
// 删除root, 删除前先与last交换,最后删除lastItem, 因为root变了, 所有需要MaxHeapifyDown
func (h *MinHeap) ExtractMin() int {
if h.HeapSize == 0 {
panic("no items")
}
// 取出最小的,即最顶端的
min := h.Items[0]
// 用最后的child填充h.Items[0]
h.Items[0] = h.Items[h.HeapSize-1]
// 删除最后的child
h.Items = h.Items[:h.HeapSize-1]
// 删除最后的child,此时HeapSize - 1
h.HeapSize--
// 重排index 0
h.MinHeapifyDown(0)
return min
}
func HeapSort(items []int) {
minHeap := BuildMinHeap(items)
fmt.Println(minHeap.Items)
for i := len(minHeap.Items) - 1; i > 0; i-- {
minHeap.Items[0], minHeap.Items[i] = minHeap.Items[i], minHeap.Items[0]
minHeap.HeapSize--
minHeap.MinHeapifyDown(0)
}
fmt.Println(minHeap.Items)
}