-
Notifications
You must be signed in to change notification settings - Fork 0
/
btree.go
169 lines (151 loc) · 3.88 KB
/
btree.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package btree
import (
"cmp"
"log"
)
type BTree[K cmp.Ordered, V any] interface {
Degree() int
Depth() int
Get(key K) *V
Add(key K, value *V) error
Remove(key K) error
Iterate() TreeIterator[K, V]
}
type bTree[K cmp.Ordered, V any] struct {
rootnode *node[K, V]
degree int
}
func (b bTree[K, V]) Degree() int {
return b.degree
}
func (b bTree[K, V]) Depth() int {
d := 0
n := b.rootnode
for !n.IsLeaf() {
d++
n = &n.Children[0]
}
return d
}
func (b bTree[K, V]) Get(key K) *V {
ne := b.rootnode.Get(key)
if ne == nil {
return nil
}
return ne.Value
}
func (b *bTree[K, V]) Add(key K, value *V) error {
nn := b.add(key, value, b.rootnode)
if nn != nil {
// a new root pushed up
b.rootnode = nn
}
return nil
}
func (b *bTree[K, V]) Remove(key K) error {
nn, err := b.remove(key, b.rootnode)
if err != nil {
return err
}
if nn != nil {
b.rootnode = nn
}
return nil
}
func (b bTree[K, V]) Iterate() TreeIterator[K, V] {
return newTreeIterator[K, V](b.rootnode)
}
func (b *bTree[K, V]) add(key K, value *V, nd *node[K, V]) *node[K, V] {
if nd.IsLeaf() {
nd.Insert(key, value)
} else {
nd = b.addToChild(key, value, nd)
}
if nd == nil || len(nd.Entries) < b.degree {
// node size within bounds, all done
return nil
}
return nd.Split()
}
func (b *bTree[K, V]) addToChild(key K, value *V, nd *node[K, V]) *node[K, V] {
i, e := nd.KeyIndex(key)
if e != nil {
// already exists, update value
e.Value = value
return nd
}
if i < 0 {
// new key greater than existing keys, use last child.
i = len(nd.Entries)
}
nn := b.add(key, value, &nd.Children[i])
if nn == nil {
// no new node due to split, all done
return nil
}
// Child has split, merge nn into parent (nd) node
nd.Entries = InsertAtIndex(nn.Entries[0], nd.Entries, i)
nd.Children[i] = nn.Children[1]
nd.Children = InsertAtIndex(nn.Children[0], nd.Children, i)
return nd
}
func (b *bTree[K, V]) remove(key K, nd *node[K, V]) (*node[K, V], error) {
if nd.IsLeaf() {
// leaf node simply deletes key and lets parent node balance entries. (Except root node, with no parent)
if err := nd.Delete(key); err != nil {
return nil, err
}
return nil, nil //TODO review if return node required
}
// non leaf / parent node
i, e := nd.KeyIndex(key)
if i < 0 {
i = len(nd.Entries)
}
if e == nil {
// not in this node, remove from child
return b.removeFromChild(key, i, nd)
}
// a parent node containing key to remove
// replace entry to be removed with the preceding entry, from the right most leaf of the child
pn := nd.getPreceeedingNode(&nd.Children[i])
lastE := pn.LastEntry()
nd.Entries[i] = *lastE
// perform a Remove of the copied entry, to remove from the leaf we stole it from and rebalnce tree
return b.removeFromChild(lastE.Key, i, nd)
}
func (b *bTree[K, V]) removeFromChild(key K, childIndex int, nd *node[K, V]) (*node[K, V], error) {
child := &nd.Children[childIndex]
if _, err := b.remove(key, child); err != nil {
return nil, err
}
if len(child.Entries) > 0 {
// child still has enough entries
return nil, nil
}
// Child now empty, Merge into one of its peers and include the entry from this node which "bridges" the merge childre,
entryIndex := nd.mergeChild(childIndex)
mergedChild := nd.Children[entryIndex]
// Ensure merged child is not too big
if len(mergedChild.Entries) >= b.degree {
// merges node now too big, perform split
nn := mergedChild.Split()
nd.Entries = InsertAtIndex(nn.Entries[0], nd.Entries, entryIndex)
nd.Children[entryIndex] = nn.Children[0]
nd.Children = InsertAtIndex(nn.Children[1], nd.Children, childIndex)
}
if len(nd.Entries) == 0 {
// If this parent now empty, pass up it's first child
return &nd.Children[0], nil
}
return nil, nil
}
func NewBTree[K cmp.Ordered, V any](degree int) BTree[K, V] {
if degree < 2 {
log.Fatalf("degree must be >= 2")
}
return &bTree[K, V]{
rootnode: &node[K, V]{},
degree: degree,
}
}