-
Notifications
You must be signed in to change notification settings - Fork 0
/
heap-sort.go
64 lines (61 loc) · 1.38 KB
/
heap-sort.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
package genericsort
// Make sure `source` is closed inside less
func HeapSort[T any](source []T, less func(i, j int) bool) []T {
result := make([]T, 0, len(source))
heapify(source, less)
var lastIndex int
for len(source) > 0 {
lastIndex = len(source) - 1
result = append(result, source[0])
source[0], source[lastIndex] = source[lastIndex], source[0]
source = source[:lastIndex]
var siftDownIndex int
var ok bool
for {
siftDownIndex, ok = sift_down(source, siftDownIndex, less)
if !ok {
break
}
}
}
return result
}
func heapify[T any](source []T, less func(i, j int) bool) {
l := len(source)
for i := l - 1; i >= 0; i-- {
k := i
var ok bool
for {
k, ok = sift_down(source, k, less)
if !ok {
break
}
}
}
}
func sift_down[T any](source []T, index int, less func(i, j int) bool) (int, bool) {
l := len(source)
child1 := (2 * index) + 1
if child1 >= l {
return index, false
}
child2 := child1 + 1
if child2 >= l {
if less(child1, index) {
source[index], source[child1] = source[child1], source[index]
return child1, true
}
return index, false
}
var candidateIndex int
if less(child1, child2) {
candidateIndex = child1
} else {
candidateIndex = child2
}
if less(candidateIndex, index) {
source[index], source[candidateIndex] = source[candidateIndex], source[index]
return candidateIndex, true
}
return index, false
}