This repository has been archived by the owner on Feb 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtree.go
97 lines (80 loc) · 1.88 KB
/
tree.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
package main
import (
"bytes"
"sort"
)
type treeNode struct {
name []byte
total uint64
self uint64
childrenNodes []*treeNode
}
func newNode(label []byte) *treeNode {
return &treeNode{
name: label,
childrenNodes: []*treeNode{},
}
}
var (
semicolon = byte(';')
)
type Tree struct {
root *treeNode
}
func NewTree() *Tree {
return &Tree{
root: newNode([]byte{}),
}
}
func prependBytes(s [][]byte, x []byte) [][]byte {
s = append(s, nil)
copy(s[1:], s)
s[0] = x
return s
}
func (n *treeNode) insert(targetLabel []byte) *treeNode {
i := sort.Search(len(n.childrenNodes), func(i int) bool {
return bytes.Compare(n.childrenNodes[i].name, targetLabel) >= 0
})
if i > len(n.childrenNodes)-1 || !bytes.Equal(n.childrenNodes[i].name, targetLabel) {
child := newNode(targetLabel)
n.childrenNodes = append(n.childrenNodes, child)
copy(n.childrenNodes[i+1:], n.childrenNodes[i:])
n.childrenNodes[i] = child
}
return n.childrenNodes[i]
}
func (t *Tree) Insert(key []byte, value uint64) {
// TODO: maybe we can optimize this slightly by just iterating over it instead of using Split?
labels := bytes.Split(key, []byte{semicolon})
node := t.root
for _, l := range labels {
buf := make([]byte, len(l))
copy(buf, l)
l = buf
n := node.insert(l)
node.total += value
node = n
}
node.self += value
node.total += value
}
func (t *Tree) Iterate(cb func(key []byte, val uint64)) {
nodes := []*treeNode{t.root}
prefixes := make([][]byte, 1)
prefixes[0] = make([]byte, 0)
for len(nodes) > 0 {
node := nodes[0]
nodes = nodes[1:]
prefix := prefixes[0]
prefixes = prefixes[1:]
label := append(prefix, semicolon)
l := node.name
label = append(label, l...)
cb(label, node.self)
nodes = append(node.childrenNodes, nodes...)
for i := 0; i < len(node.childrenNodes); i++ {
prefixes = prependBytes(prefixes, label)
}
}
}