1
1
/**
2
+ * The Size Balanced Tree (SBT) is a balanced binary search tree that uses the
3
+ * size of subtrees to rebalance itself.
4
+ *
5
+ * See nice article about the SBT:
6
+ * http://wcipeg.com/wiki/Size_Balanced_Tree#Insertion
7
+ *
8
+ * Read the excellent research paper in the research_paper/ folder.
2
9
*
3
10
* @author William Fiset, william.alexandre.fiset@gmail.com
4
11
**/
5
12
6
- public class SizeBalancedTree <T extends Comparable <T >> {
13
+ public class SizeBalancedTree <T extends Comparable <T >> implements Iterable < T > {
7
14
8
- // Tracks the number of nodes in this BST
15
+ private static final int DEFAULT_SIZE = 16 ;
16
+
17
+ // Tracks the number of nodes in this tree.
9
18
private int nodeCount = 0 ;
10
19
11
- // This BST is a rooted tree so we maintain a handle on the root node
20
+ // This is a rooted tree so we maintain a handle on the root node.
12
21
private Node root = null ;
13
22
14
- // Internal node containing node references
15
- // and the actual node data
16
- private class Node {
17
- T data ;
23
+ // Size tracks the number of children nodes below this number.
24
+ private int [] sz = new int [DEFAULT_SIZE ];
25
+
26
+ // TODO: Implement TreePrinter interface
27
+ class Node {
28
+
29
+ T value ;
30
+
31
+ int id ;
32
+
18
33
Node left , right ;
19
- public Node ( Node left , Node right , T elem ) {
20
- this . data = elem ;
21
- this .left = left ;
22
- this . right = right ;
34
+
35
+ public Node ( T value ) {
36
+ this .value = value ;
37
+ id = nodeCount ;
23
38
}
24
39
}
25
40
26
- // Check if this binary tree is empty
41
+ // Check if the tree is empty.
27
42
public boolean isEmpty () {
28
43
return size () == 0 ;
29
44
}
@@ -44,33 +59,72 @@ public boolean add(T elem) {
44
59
45
60
// Otherwise add this element to the binary tree
46
61
} else {
62
+ checkSize ();
47
63
root = add (root , elem );
48
64
nodeCount ++;
49
65
return true ;
50
66
}
51
67
52
68
}
53
69
70
+ private void checkSize () {
71
+ if (nodeCount + 1 == sz .length ) {
72
+ int [] newSz = new int [sz .length * 2 ];
73
+ System .arraycopy (sz , 0 , newSz , 0 , sz .length );
74
+ sz = newSz ;
75
+ }
76
+ }
77
+
54
78
// Private method to recursively add a value in the binary tree
55
79
private Node add (Node node , T elem ) {
56
80
57
81
// Base case: found a leaf node
58
82
if (node == null ) {
59
- node = new Node (null , null , elem );
60
-
83
+ node = new Node (elem );
61
84
} else {
85
+
86
+ sz [node .id ]++;
87
+
62
88
// Pick a subtree to insert element
63
- if (elem .compareTo (node .data ) < 0 ) {
89
+ if (elem .compareTo (node .value ) < 0 ) {
64
90
node .left = add (node .left , elem );
65
91
} else {
66
92
node .right = add (node .right , elem );
67
93
}
68
94
}
69
95
96
+ // Rebalance
70
97
return node ;
71
98
72
99
}
73
100
101
+ private int sz (Node node ) {
102
+ if (node == null ) return 0 ;
103
+ return sz [node .id ];
104
+ }
105
+
106
+ private Node rightRotate (Node node ) {
107
+ Node child = node .left ;
108
+ node .left = child .right ;
109
+ child .right = node ;
110
+ sz [child .id ] = sz (node );
111
+ sz [node .id ] = sz (node .left ) + sz (node .right ) + 1 ;
112
+ return child ;
113
+ }
114
+
115
+ private Node leftRotate (Node node ) {
116
+ Node child = node .right ;
117
+ node .right = child .left ;
118
+ child .left = node ;
119
+ sz [child .id ] = sz (node );
120
+ sz [node .id ] = sz (child .left ) + sz (child .right ) + 1 ;
121
+ return child ;
122
+ }
123
+
124
+ private Node leftRotate (Node node ) {
125
+ return null ;
126
+ }
127
+
74
128
// Remove a value from this binary tree if it exists, O(n)
75
129
public boolean remove (T elem ) {
76
130
@@ -89,7 +143,7 @@ private Node remove(Node node, T elem) {
89
143
90
144
if (node == null ) return null ;
91
145
92
- int cmp = elem .compareTo (node .data );
146
+ int cmp = elem .compareTo (node .value );
93
147
94
148
// Dig into left subtree, the value we're looking
95
149
// for is smaller than the current value
@@ -111,7 +165,7 @@ private Node remove(Node node, T elem) {
111
165
112
166
Node rightChild = node .right ;
113
167
114
- node .data = null ;
168
+ node .value = null ;
115
169
node = null ;
116
170
117
171
return rightChild ;
@@ -123,7 +177,7 @@ private Node remove(Node node, T elem) {
123
177
124
178
Node leftChild = node .left ;
125
179
126
- node .data = null ;
180
+ node .value = null ;
127
181
node = null ;
128
182
129
183
return leftChild ;
@@ -140,19 +194,19 @@ private Node remove(Node node, T elem) {
140
194
Node tmp = findMin (node .right );
141
195
142
196
// Swap the data
143
- node .data = tmp .data ;
197
+ node .value = tmp .value ;
144
198
145
199
// Go into the right subtree and remove the leftmost node we
146
200
// found and swapped data with. This prevents us from having
147
201
// two nodes in our tree with the same value.
148
- node .right = remove (node .right , tmp .data );
202
+ node .right = remove (node .right , tmp .value );
149
203
150
204
// If instead we wanted to find the largest node in the left
151
205
// subtree as opposed to smallest node in the right subtree
152
206
// here is what we would do:
153
207
// Node tmp = findMax(node.left);
154
- // node.data = tmp.data ;
155
- // node.left = remove(node.left, tmp.data );
208
+ // node.value = tmp.value ;
209
+ // node.left = remove(node.left, tmp.value );
156
210
157
211
}
158
212
@@ -176,30 +230,34 @@ private Node findMax(Node node) {
176
230
return node ;
177
231
}
178
232
179
- // returns true is the element exists in the tree
180
- public boolean contains (T elem ) {
181
- return contains (root , elem );
182
- }
183
-
184
- // private recursive method to find an element in the tree
185
- private boolean contains (Node node , T elem ) {
233
+ // Return true/false depending on whether a value exists in the tree.
234
+ public boolean contains (T value ) {
186
235
187
- // Base case: reached bottom, value not found
188
- if (node == null ) return false ;
236
+ Node node = root ;
189
237
190
- int cmp = elem .compareTo (node .data );
191
-
192
- // Dig into the left subtree because the value we're
193
- // looking for is smaller than the current value
194
- if (cmp < 0 ) return contains (node .left , elem );
238
+ if (node == null || value == null ) return false ;
195
239
196
- // Dig into the right subtree because the value we're
197
- // looking for is greater than the current value
198
- else if (cmp > 0 ) return contains (node .right , elem );
199
-
200
- // We found the value we were looking for
201
- else return true ;
240
+ while (node != null ) {
241
+
242
+ // Compare current value to the value in the node.
243
+ int cmp = value .compareTo (node .value );
244
+
245
+ // Dig into left subtree.
246
+ if (cmp < 0 ) node = node .left ;
247
+
248
+ // Dig into right subtree.
249
+ else if (cmp > 0 ) node = node .right ;
250
+
251
+ // Found value in tree.
252
+ else return true ;
253
+ }
254
+
255
+ return false ;
256
+ }
202
257
258
+ // TODO: Implement iterator. See other BST for examples.
259
+ public java .util .Iterator <T > iterator () {
260
+ return null ;
203
261
}
204
262
205
263
public static void main (String [] args ) {
0 commit comments