-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHeap.go
130 lines (111 loc) · 3 KB
/
Heap.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package heap
// This is an implementation of a binary heap
type Heap struct {
Data []int
IsMinHeap bool
}
func CreateNewHeap(isMinHeap bool) *Heap {
return &Heap{
Data: []int{},
IsMinHeap: isMinHeap,
}
}
// Insert adds a new element to the heap and maintains the heap property
func (h *Heap) Insert(value int) {
h.Data = append(h.Data, value)
h.HeapifyUp(len(h.Data) - 1)
}
// HeapifyUp moves the newly added element up to maintain the heap property
func (h *Heap) HeapifyUp(index int) {
for index > 0 {
parentIndex := (index - 1) / 2
if h.compare(h.Data[index], h.Data[parentIndex]) {
h.swap(index, parentIndex)
index = parentIndex
} else {
break
}
}
}
// HeapifyDown moves the element at index down to maintain the heap property
func (h *Heap) HeapifyDown(index int) {
lastIndex := len(h.Data) - 1
l, r := 2*index+1, 2*index+2
childToCompare := 0
// Continue while there is at least one child
for l <= lastIndex {
if r <= lastIndex && h.compare(h.Data[r], h.Data[l]) { // Compare left and right children
childToCompare = r
} else {
childToCompare = l
}
// Compare the selected child with the current node
if h.compare(h.Data[childToCompare], h.Data[index]) {
h.swap(index, childToCompare)
index = childToCompare
l, r = 2*index+1, 2*index+2
} else {
break
}
}
}
// compare returns true if the order is correct based on the heap type (min-heap or max-heap)
func (h *Heap) compare(child, parent int) bool {
if h.IsMinHeap {
return child < parent // min-heap: child should be less than parent
}
return child > parent // max-heap: child should be greater than parent
}
// swap swaps two elements in the array
func (h *Heap) swap(i1, i2 int) {
h.Data[i1], h.Data[i2] = h.Data[i2], h.Data[i1]
}
// GetMin returns the minimum value for a min-heap, or the root in a max-heap
func (h *Heap) GetMin() int {
if h.IsMinHeap && len(h.Data) > 0 {
return h.Data[0]
} else if !h.IsMinHeap && len(h.Data) > 0 {
minVal := h.Data[len(h.Data)/2]
for i := len(h.Data) / 2; i < len(h.Data); i++ {
if h.Data[i] < minVal {
minVal = h.Data[i]
}
}
return minVal
}
return 0 // heap is empty
}
// GetMax returns the maximum value for a max-heap, or the root in a min-heap
func (h *Heap) GetMax() int {
if !h.IsMinHeap && len(h.Data) > 0 {
return h.Data[0]
} else if h.IsMinHeap && len(h.Data) > 0 {
maxVal := h.Data[len(h.Data)/2]
for i := len(h.Data) / 2; i < len(h.Data); i++ {
if h.Data[i] > maxVal {
maxVal = h.Data[i]
}
}
return maxVal
}
return 0 // heap is empty
}
// BuildHeap constructs a heap from an unsorted slice of integers
func (h *Heap) BuildHeap(data []int) {
h.Data = data
for i := len(data)/2 - 1; i >= 0; i-- {
h.HeapifyDown(i)
}
}
// ExtractRoot removes and returns the root of the heap
func (h *Heap) ExtractRoot() int {
if len(h.Data) == 0 {
return 0
}
// Swap the root with the last element
root := h.Data[0]
h.Data[0] = h.Data[len(h.Data)-1]
h.Data = h.Data[:len(h.Data)-1]
h.HeapifyDown(0)
return root
}