-
Notifications
You must be signed in to change notification settings - Fork 0
/
heap.go
81 lines (70 loc) · 1.86 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
package heap
import "unsafe"
// Max is a max-heap used to keep track of nearest neighbors.
type Max[T int | uint64] struct {
distances []int
lastDistance *int
values []T
lastValue *T
len int
}
const unsafeSizeofInt = unsafe.Sizeof(int(0))
func MakeMax[T int | uint64](distances []int, value []T) Max[T] {
return Max[T]{
distances: distances,
lastDistance: (*int)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(distances)), unsafeSizeofInt*uintptr(len(distances)-1))),
values: value,
lastValue: (*T)(unsafe.Add(unsafe.Pointer(unsafe.SliceData(value)), unsafe.Sizeof(T(0))*uintptr(len(value)-1))),
}
}
func (me *Max[T]) Len() int {
return me.len
}
func (me *Max[T]) swap(i, j int) {
me.distances[i], me.distances[j] = me.distances[j], me.distances[i]
me.values[i], me.values[j] = me.values[j], me.values[i]
}
func (me *Max[T]) less(i, j int) bool {
return me.distances[i] > me.distances[j]
}
func (me *Max[T]) PushPop(dist int, value T) {
n := me.len
*me.lastDistance = dist
*me.lastValue = value
me.up(n)
me.swap(0, n)
// me.down(0, n)
i := 0
for {
l := 2*i + 1 // Left child
if l >= n || l < 0 { // If no left child, break
break
}
j := l
if r := l + 1; r < n && me.less(r, l) { // If right child exists and is smaller, select right child
j = r
}
if !me.less(j, i) { // If parent is smaller than selected child, break
break
}
me.swap(i, j) // Swap parent with child
i = j // Continue pushing down
}
}
func (me *Max[T]) Push(dist int, value T) {
n := me.len
me.distances[n] = dist
me.values[n] = value
me.len = n + 1
me.up(n)
}
func (me *Max[T]) up(i int) {
for {
p := (i - 1) / 2 // Parent index
if p == i || !me.less(i, p) { // If parent is larger or i is root, stop
break
}
me.swap(p, i) // Swap child with parent
i = p // Continue moving up
}
}