-
Notifications
You must be signed in to change notification settings - Fork 0
/
selfbalancingtree.go
243 lines (205 loc) · 4.45 KB
/
selfbalancingtree.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
///
/// Author Garr Godfrey
///
/// A self-balancing binary tree in GO. Guarantee a O(log N) lookup with an O(log^2 N) insert.
///
package main
import (
"fmt"
"strings"
)
type Compare interface {
Compare(b Compare) int
}
type Node struct {
value interface{}
left * Node
right * Node
count int
}
type tree struct {
head * Node
}
///
/// Allow strings, int or any type that supports the Compare interface.
/// Can easily add floats or other primitive types to this.
///
func CompareAny(a,b interface{}) int {
v,ok := a.(Compare)
if (ok) {
return v.Compare(b.(Compare))
}
v2,ok2 := a.(string)
if (ok2) {
return strings.Compare(v2,b.(string))
}
v3,ok3 := a.(int)
if (ok3) {
return v3 - b.(int)
}
return 0
}
///
/// Find the smallest item in this subtree so we can move it
///
func (t * Node) leftmost() *Node {
if t == nil {
return nil
}
if (t.left == nil) {
// current node is the smallest value, remove and replace with
// the right hand side of the tree
return t
}
leftmost := t.left.leftmost()
t.left = leftmost.right
t.count -= 1
leftmost.right = t
// now right hand side may be heavier as we've lowered the count
// on the left. Rebalance as we are rebalancing. In order to save
// checking nil for left, we use the count we already have on t
if t.right != nil && t.right.count > t.count-t.right.count {
newcenter := t.right.leftmost()
newcenter.left = t.left.add(t.value)
newcenter.count += newcenter.left.count
leftmost.right = newcenter
}
leftmost.count = t.count + 1
return leftmost
}
///
/// find the right most (greatest) node in this subtree.
///
func (t * Node) rightmost() *Node {
if t == nil {
return nil
}
if (t.right== nil) {
// current node is the biggest value, remove and replace with
// the left hand side of the tree
return t
}
rightmost := t.right.rightmost()
t.count -= 1;
t.right = rightmost.left
rightmost.left = t
// now left hand side may be heavier as we've lowered the count
// on the right. Rebalance as we are rebalancing. In order to save
// checking nil for right, we use the count we already have on t
if t.left != nil && t.left.count > t.count-t.left.count {
newcenter := t.left.rightmost()
newcenter.right = t.right.add(t.value)
newcenter.count += newcenter.right.count
rightmost.left = newcenter
}
// since rightmost never has a right left, and the left leg is t, its
// count should always be t.count+1
rightmost.count = t.count+1
return rightmost
}
/// insert and return the new center node
func (t * Node) add( d interface{}) *Node {
if (t == nil) {
return &Node{value: d, count: 1}
}
var rcount, lcount int
if CompareAny(t.value, d) < 0 {
if t.right == nil {
t.right = &Node{value: d, count: 1}
} else {
t.right = t.right.add(d)
}
} else if t.left == nil {
t.left = &Node{value: d, count: 1}
} else {
t.left = t.left.add(d)
}
t.count += 1
//
// now rebalance
if rcount=0; t.right != nil {
rcount = t.right.count
}
if lcount=0; t.left != nil {
lcount = t.left.count
}
if rcount - lcount >= 2 {
// adjust tree, making our right node the new
// center node and put our center node down the
// left hand side
newcenter := t.right.leftmost()
newcenter.left = t.left.add(t.value)
newcenter.count += newcenter.left.count
return newcenter
}
if (lcount - rcount >= 2) {
newcenter := t.left.rightmost()
newcenter.right = t.right.add(t.value)
newcenter.count += newcenter.right.count
return newcenter
}
return t
}
func (t * Node) walk(c chan interface{}) {
if (t == nil) {
return
}
t.left.walk(c)
c <- t.value
t.right.walk(c)
}
///
/// send all elements through c in sorted order.
///
func (t * tree) walk(c chan interface{}) {
t.head.walk(c)
close(c)
}
///
/// add the new element to our tree, potentially changing our head node.
///
func (t * tree) add (d interface{}) {
t.head = t.head.add(d)
}
///
/// Our main funciton tests the functionality of our self balancing tree
///
func main() {
t := &tree{}
t.add("a")
t.add("ab")
t.add("ac")
t.add("ae")
t.add("af")
t.add("f")
t.add("e")
t.add("e9")
t.add("e8")
t.add("e7")
t.add("e3")
t.add("e2")
t.add("d")
t.add("b")
t.add("c")
t.add("c1")
t.add("c2")
t.add("c3")
t.add("c4")
t.add("c5")
t.add("c6")
t.add("b1")
t.add("v6")
t.add("v5")
t.add("bx")
t.add("qr")
t.add("v4")
t.add("v3")
t.add("ba")
t.add("v2")
t.add("cx")
c := make(chan interface{}, 3)
go t.walk(c)
for msg := range c {
fmt.Println(msg)
}
}