|
1 | 1 | package sort
|
2 | 2 |
|
| 3 | +import "github.com/TheAlgorithms/Go/constraints" |
| 4 | + |
3 | 5 | type MaxHeap struct {
|
4 | 6 | slice []Comparable
|
5 | 7 | heapSize int
|
6 | 8 | indices map[int]int
|
7 | 9 | }
|
8 | 10 |
|
9 |
| -func buildMaxHeap(slice0 []int) MaxHeap { |
10 |
| - var slice []Comparable |
11 |
| - for _, i := range slice0 { |
12 |
| - slice = append(slice, Int(i)) |
13 |
| - } |
14 |
| - h := MaxHeap{} |
15 |
| - h.Init(slice) |
16 |
| - return h |
17 |
| -} |
18 |
| - |
19 | 11 | func (h *MaxHeap) Init(slice []Comparable) {
|
20 | 12 | if slice == nil {
|
21 | 13 | slice = make([]Comparable, 0)
|
@@ -73,62 +65,73 @@ func (h MaxHeap) updateidx(i int) {
|
73 | 65 | h.indices[h.slice[i].Idx()] = i
|
74 | 66 | }
|
75 | 67 |
|
| 68 | +func (h *MaxHeap) swap(i, j int) { |
| 69 | + h.slice[i], h.slice[j] = h.slice[j], h.slice[i] |
| 70 | + h.updateidx(i) |
| 71 | + h.updateidx(j) |
| 72 | +} |
| 73 | + |
| 74 | +func (h MaxHeap) more(i, j int) bool { |
| 75 | + return h.slice[i].More(h.slice[j]) |
| 76 | +} |
| 77 | + |
76 | 78 | func (h MaxHeap) heapifyUp(i int) {
|
77 | 79 | if i == 0 {
|
78 | 80 | return
|
79 | 81 | }
|
80 | 82 | p := i / 2
|
81 | 83 |
|
82 | 84 | if h.slice[i].More(h.slice[p]) {
|
83 |
| - h.slice[i], h.slice[p] = h.slice[p], h.slice[i] |
84 |
| - h.updateidx(i) |
85 |
| - h.updateidx(p) |
| 85 | + h.swap(i, p) |
86 | 86 | h.heapifyUp(p)
|
87 | 87 | }
|
88 | 88 | }
|
89 | 89 |
|
90 | 90 | func (h MaxHeap) heapifyDown(i int) {
|
| 91 | + heapifyDown(h.slice, h.heapSize, i, h.more, h.swap) |
| 92 | +} |
| 93 | + |
| 94 | +func heapifyDown[T any](slice []T, N, i int, moreFunc func(i, j int) bool, swapFunc func(i, j int)) { |
91 | 95 | l, r := 2*i+1, 2*i+2
|
92 | 96 | max := i
|
93 | 97 |
|
94 |
| - if l < h.heapSize && h.slice[l].More(h.slice[max]) { |
| 98 | + if l < N && moreFunc(l, max) { |
95 | 99 | max = l
|
96 | 100 | }
|
97 |
| - if r < h.heapSize && h.slice[r].More(h.slice[max]) { |
| 101 | + if r < N && moreFunc(r, max) { |
98 | 102 | max = r
|
99 | 103 | }
|
100 | 104 | if max != i {
|
101 |
| - h.slice[i], h.slice[max] = h.slice[max], h.slice[i] |
102 |
| - h.updateidx(i) |
103 |
| - h.updateidx(max) |
104 |
| - h.heapifyDown(max) |
| 105 | + swapFunc(i, max) |
| 106 | + |
| 107 | + heapifyDown(slice, N, max, moreFunc, swapFunc) |
105 | 108 | }
|
106 | 109 | }
|
107 | 110 |
|
108 | 111 | type Comparable interface {
|
109 | 112 | Idx() int
|
110 | 113 | More(any) bool
|
111 | 114 | }
|
112 |
| -type Int int |
113 | 115 |
|
114 |
| -func (a Int) More(b any) bool { |
115 |
| - return a > b.(Int) |
116 |
| -} |
117 |
| -func (a Int) Idx() int { |
118 |
| - return int(a) |
119 |
| -} |
| 116 | +func HeapSort[T constraints.Ordered](slice []T) []T { |
| 117 | + N := len(slice) |
120 | 118 |
|
121 |
| -func HeapSort(slice []int) []int { |
122 |
| - h := buildMaxHeap(slice) |
123 |
| - for i := len(h.slice) - 1; i >= 1; i-- { |
124 |
| - h.slice[0], h.slice[i] = h.slice[i], h.slice[0] |
125 |
| - h.heapSize-- |
126 |
| - h.heapifyDown(0) |
| 119 | + moreFunc := func(i, j int) bool { |
| 120 | + return slice[i] > slice[j] |
| 121 | + } |
| 122 | + swapFunc := func(i, j int) { |
| 123 | + slice[i], slice[j] = slice[j], slice[i] |
| 124 | + } |
| 125 | + |
| 126 | + // build a maxheap |
| 127 | + for i := N/2 - 1; i >= 0; i-- { |
| 128 | + heapifyDown(slice, N, i, moreFunc, swapFunc) |
127 | 129 | }
|
128 | 130 |
|
129 |
| - res := []int{} |
130 |
| - for _, i := range h.slice { |
131 |
| - res = append(res, int(i.(Int))) |
| 131 | + for i := N - 1; i > 0; i-- { |
| 132 | + slice[i], slice[0] = slice[0], slice[i] |
| 133 | + heapifyDown(slice, i, 0, moreFunc, swapFunc) |
132 | 134 | }
|
133 |
| - return res |
| 135 | + |
| 136 | + return slice |
134 | 137 | }
|
0 commit comments