Skip to content

Commit e4a5da4

Browse files
author
Justin Wetherell
committed
Streamlined some tree code in an effort to improve performance
1 parent d76bb72 commit e4a5da4

File tree

3 files changed

+114
-128
lines changed

3 files changed

+114
-128
lines changed

src/com/jwetherell/algorithms/data_structures/BinarySearchTree.java

+10-37
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ public class BinarySearchTree<T extends Comparable<T>> implements ITree<T> {
3030

3131
protected static final Random RANDOM = new Random();
3232

33-
protected enum Position {
34-
LEFT, RIGHT
35-
}
36-
3733
protected Node<T> root = null;
3834
protected int size = 0;
3935
protected INodeCreator<T> creator = null;
@@ -157,39 +153,28 @@ protected Node<T> getNode(T value) {
157153
* Root of tree to rotate left.
158154
*/
159155
protected void rotateLeft(Node<T> node) {
160-
Position parentPosition = null;
161156
Node<T> parent = node.parent;
162-
if (parent != null) {
163-
if (node.equals(parent.lesser)) {
164-
// Lesser
165-
parentPosition = Position.LEFT;
166-
} else {
167-
// Greater
168-
parentPosition = Position.RIGHT;
169-
}
170-
}
171-
172157
Node<T> greater = node.greater;
173-
node.greater = null;
174158
Node<T> lesser = greater.lesser;
175159

176160
greater.lesser = node;
177161
node.parent = greater;
178162

179163
node.greater = lesser;
164+
180165
if (lesser != null)
181166
lesser.parent = node;
182167

183-
if (parent!=null && parentPosition != null) {
184-
if (parentPosition == Position.LEFT) {
168+
if (parent!=null) {
169+
if (node.equals(parent.lesser)) {
185170
parent.lesser = greater;
186171
} else {
187172
parent.greater = greater;
188173
}
189174
greater.parent = parent;
190175
} else {
191176
root = greater;
192-
greater.parent = null;
177+
root.parent = null;
193178
}
194179
}
195180

@@ -200,39 +185,28 @@ protected void rotateLeft(Node<T> node) {
200185
* Root of tree to rotate left.
201186
*/
202187
protected void rotateRight(Node<T> node) {
203-
Position parentPosition = null;
204188
Node<T> parent = node.parent;
205-
if (parent != null) {
206-
if (node.equals(parent.lesser)) {
207-
// Lesser
208-
parentPosition = Position.LEFT;
209-
} else {
210-
// Greater
211-
parentPosition = Position.RIGHT;
212-
}
213-
}
214-
215189
Node<T> lesser = node.lesser;
216-
node.lesser = null;
217190
Node<T> greater = lesser.greater;
218191

219192
lesser.greater = node;
220193
node.parent = lesser;
221194

222195
node.lesser = greater;
196+
223197
if (greater != null)
224198
greater.parent = node;
225199

226-
if (parent!=null && parentPosition != null) {
227-
if (parentPosition == Position.LEFT) {
200+
if (parent!=null) {
201+
if (node.equals(parent.lesser)) {
228202
parent.lesser = lesser;
229203
} else {
230204
parent.greater = lesser;
231205
}
232206
lesser.parent = parent;
233207
} else {
234208
root = lesser;
235-
lesser.parent = null;
209+
root.parent = null;
236210
}
237211
}
238212

@@ -338,11 +312,10 @@ protected Node<T> getReplacementNode(Node<T> nodeToRemoved) {
338312
// Using the less subtree
339313
replacement = nodeToRemoved.lesser;
340314
} else if (nodeToRemoved.greater != null && nodeToRemoved.lesser == null) {
341-
// Using the greater subtree (there is no lesser subtree, no
342-
// refactoring)
315+
// Using the greater subtree (there is no lesser subtree, no refactoring)
343316
replacement = nodeToRemoved.greater;
344317
} else if (nodeToRemoved.greater != null && nodeToRemoved.lesser != null) {
345-
// Two children
318+
// Two children.
346319
// Add some randomness to deletions, so we don't always use the
347320
// greatest/least on deletion
348321
if (modifications % 2 != 0) {

src/com/jwetherell/algorithms/data_structures/RedBlackTree.java

+103-90
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ public RedBlackTree(INodeCreator<T> creator) {
5353
@Override
5454
protected Node<T> addValue(T id) {
5555
RedBlackNode<T> nodeAdded = null;
56-
boolean added = false;
5756
if (root == null) {
5857
// Case 1 - The current node is at the root of the tree.
5958

@@ -63,7 +62,6 @@ protected Node<T> addValue(T id) {
6362
root.greater = this.creator.createNewNode(root, null);
6463

6564
nodeAdded = (RedBlackNode<T>) root;
66-
added = true;
6765
} else {
6866
// Insert node like a BST would
6967
Node<T> node = root;
@@ -77,7 +75,6 @@ protected Node<T> addValue(T id) {
7775
node.greater = this.creator.createNewNode(node, null);
7876

7977
nodeAdded = (RedBlackNode<T>) node;
80-
added = true;
8178
break;
8279
} else if (id.compareTo(node.id) <= 0) {
8380
node = node.lesser;
@@ -87,7 +84,7 @@ protected Node<T> addValue(T id) {
8784
}
8885
}
8986

90-
if (added == true) {
87+
if (nodeAdded != null) {
9188
balanceAfterInsert(nodeAdded);
9289
size++;
9390
}
@@ -119,7 +116,7 @@ private void balanceAfterInsert(RedBlackNode<T> begin) {
119116
}
120117

121118
RedBlackNode<T> grandParent = node.getGrandParent();
122-
RedBlackNode<T> uncle = node.getUncle();
119+
RedBlackNode<T> uncle = node.getUncle(grandParent);
123120
if (parent.color == RED && uncle.color == RED) {
124121
// Case 3 - If both the parent and the uncle are red, then both of
125122
// them can be repainted black and the grandparent becomes
@@ -131,43 +128,44 @@ private void balanceAfterInsert(RedBlackNode<T> begin) {
131128
grandParent.color = RED;
132129
balanceAfterInsert(grandParent);
133130
}
134-
} else {
135-
if (parent.color == RED && uncle.color == BLACK) {
136-
// Case 4 - The parent is red but the uncle is black; also, the
137-
// current node is the right child of parent, and parent in turn
138-
// is the left child of its parent grandparent.
139-
if (node.equals(parent.greater) && parent.equals(grandParent.lesser)) {
140-
// right-left
141-
rotateLeft(parent);
142-
node = (RedBlackNode<T>) node.lesser;
143-
144-
grandParent = node.getGrandParent();
145-
parent = (RedBlackNode<T>) node.parent;
146-
uncle = node.getUncle();
147-
} else if (node.equals(parent.lesser) && parent.equals(grandParent.greater)) {
148-
// left-right
149-
rotateRight(parent);
150-
node = (RedBlackNode<T>) node.greater;
151-
152-
grandParent = node.getGrandParent();
153-
parent = (RedBlackNode<T>) node.parent;
154-
uncle = node.getUncle();
155-
}
131+
return;
132+
}
133+
134+
if (parent.color == RED && uncle.color == BLACK) {
135+
// Case 4 - The parent is red but the uncle is black; also, the
136+
// current node is the right child of parent, and parent in turn
137+
// is the left child of its parent grandparent.
138+
if (node.equals(parent.greater) && parent.equals(grandParent.lesser)) {
139+
// right-left
140+
rotateLeft(parent);
141+
142+
node = (RedBlackNode<T>) node.lesser;
143+
parent = (RedBlackNode<T>) node.parent;
144+
grandParent = node.getGrandParent();
145+
uncle = node.getUncle(grandParent);
146+
} else if (node.equals(parent.lesser) && parent.equals(grandParent.greater)) {
147+
// left-right
148+
rotateRight(parent);
149+
150+
node = (RedBlackNode<T>) node.greater;
151+
parent = (RedBlackNode<T>) node.parent;
152+
grandParent = node.getGrandParent();
153+
uncle = node.getUncle(grandParent);
156154
}
155+
}
157156

158-
if (parent.color == RED && uncle.color == BLACK) {
159-
// Case 5 - The parent is red but the uncle is black, the
160-
// current node is the left child of parent, and parent is the
161-
// left child of its parent G.
162-
parent.color = BLACK;
163-
grandParent.color = RED;
164-
if (node.equals(parent.lesser) && parent.equals(grandParent.lesser)) {
165-
// left-left
166-
rotateRight(grandParent);
167-
} else if (node.equals(parent.greater) && parent.equals(grandParent.greater)) {
168-
// right-right
169-
rotateLeft(grandParent);
170-
}
157+
if (parent.color == RED && uncle.color == BLACK) {
158+
// Case 5 - The parent is red but the uncle is black, the
159+
// current node is the left child of parent, and parent is the
160+
// left child of its parent G.
161+
parent.color = BLACK;
162+
grandParent.color = RED;
163+
if (node.equals(parent.lesser) && parent.equals(grandParent.lesser)) {
164+
// left-left
165+
rotateRight(grandParent);
166+
} else if (node.equals(parent.greater) && parent.equals(grandParent.greater)) {
167+
// right-right
168+
rotateLeft(grandParent);
171169
}
172170
}
173171
}
@@ -287,11 +285,13 @@ private boolean balanceAfterDelete(RedBlackNode<T> node) {
287285
sibling.color = BLACK;
288286
if (node.equals(parent.lesser)) {
289287
rotateLeft(parent);
288+
290289
// Rotation, need to update parent/sibling
291290
parent = (RedBlackNode<T>) node.parent;
292291
sibling = node.getSibling();
293292
} else if (node.equals(parent.greater)) {
294293
rotateRight(parent);
294+
295295
// Rotation, need to update parent/sibling
296296
parent = (RedBlackNode<T>) node.parent;
297297
sibling = node.getSibling();
@@ -301,64 +301,73 @@ private boolean balanceAfterDelete(RedBlackNode<T> node) {
301301
}
302302
}
303303

304-
if (parent.color == BLACK && sibling.color == BLACK
304+
if (parent.color == BLACK
305+
&& sibling.color == BLACK
305306
&& ((RedBlackNode<T>) sibling.lesser).color == BLACK
306307
&& ((RedBlackNode<T>) sibling.greater).color == BLACK
307308
) {
308309
// Case 3 - parent, sibling, and sibling's children are black.
309310
sibling.color = RED;
310-
boolean result = balanceAfterDelete(parent);
311-
if (!result) return false;
312-
} else if (parent.color == RED && sibling.color == BLACK
313-
&& ((RedBlackNode<T>) sibling.lesser).color == BLACK
314-
&& ((RedBlackNode<T>) sibling.greater).color == BLACK
311+
return balanceAfterDelete(parent);
312+
}
313+
314+
if (parent.color == RED
315+
&& sibling.color == BLACK
316+
&& ((RedBlackNode<T>) sibling.lesser).color == BLACK
317+
&& ((RedBlackNode<T>) sibling.greater).color == BLACK
315318
) {
316319
// Case 4 - sibling and sibling's children are black, but parent is red.
317320
sibling.color = RED;
318321
parent.color = BLACK;
319-
} else {
320-
if (sibling.color == BLACK) {
321-
// Case 5 - sibling is black, sibling's left child is red,
322-
// sibling's right child is black, and node is the left child of
323-
// its parent.
324-
if (node.equals(parent.lesser)
325-
&& ((RedBlackNode<T>) sibling.lesser).color == RED
326-
&& ((RedBlackNode<T>) sibling.greater).color == BLACK
327-
) {
328-
sibling.color = RED;
329-
((RedBlackNode<T>) sibling.lesser).color = RED;
330-
rotateRight(sibling);
331-
// Rotation, need to update parent/sibling
332-
parent = (RedBlackNode<T>) node.parent;
333-
sibling = node.getSibling();
334-
} else if (node.equals(parent.greater)
335-
&& ((RedBlackNode<T>) sibling.lesser).color == BLACK
336-
&& ((RedBlackNode<T>) sibling.greater).color == RED
337-
) {
338-
sibling.color = RED;
339-
((RedBlackNode<T>) sibling.greater).color = RED;
340-
rotateLeft(sibling);
341-
// Rotation, need to update parent/sibling
342-
parent = (RedBlackNode<T>) node.parent;
343-
sibling = node.getSibling();
344-
}
345-
}
322+
return true;
323+
}
346324

347-
// Case 6 - sibling is black, sibling's right child is red, and node
348-
// is the left child of its parent.
349-
sibling.color = parent.color;
350-
parent.color = BLACK;
351-
if (node.equals(parent.lesser)) {
352-
((RedBlackNode<T>) sibling.greater).color = BLACK;
353-
rotateLeft(node.parent);
354-
} else if (node.equals(parent.greater)) {
355-
((RedBlackNode<T>) sibling.lesser).color = BLACK;
356-
rotateRight(node.parent);
357-
} else {
358-
System.err.println("Yikes! I'm not related to my parent. " + node.toString());
359-
return false;
325+
if (sibling.color == BLACK) {
326+
// Case 5 - sibling is black, sibling's left child is red,
327+
// sibling's right child is black, and node is the left child of
328+
// its parent.
329+
if (node.equals(parent.lesser)
330+
&& ((RedBlackNode<T>) sibling.lesser).color == RED
331+
&& ((RedBlackNode<T>) sibling.greater).color == BLACK
332+
) {
333+
sibling.color = RED;
334+
((RedBlackNode<T>) sibling.lesser).color = RED;
335+
336+
rotateRight(sibling);
337+
338+
// Rotation, need to update parent/sibling
339+
parent = (RedBlackNode<T>) node.parent;
340+
sibling = node.getSibling();
341+
} else if (node.equals(parent.greater)
342+
&& ((RedBlackNode<T>) sibling.lesser).color == BLACK
343+
&& ((RedBlackNode<T>) sibling.greater).color == RED
344+
) {
345+
sibling.color = RED;
346+
((RedBlackNode<T>) sibling.greater).color = RED;
347+
348+
rotateLeft(sibling);
349+
350+
// Rotation, need to update parent/sibling
351+
parent = (RedBlackNode<T>) node.parent;
352+
sibling = node.getSibling();
360353
}
361354
}
355+
356+
// Case 6 - sibling is black, sibling's right child is red, and node
357+
// is the left child of its parent.
358+
sibling.color = parent.color;
359+
parent.color = BLACK;
360+
if (node.equals(parent.lesser)) {
361+
((RedBlackNode<T>) sibling.greater).color = BLACK;
362+
rotateLeft(node.parent);
363+
} else if (node.equals(parent.greater)) {
364+
((RedBlackNode<T>) sibling.lesser).color = BLACK;
365+
rotateRight(node.parent);
366+
} else {
367+
System.err.println("Yikes! I'm not related to my parent. " + node.toString());
368+
return false;
369+
}
370+
362371
return true;
363372
}
364373

@@ -449,17 +458,21 @@ protected RedBlackNode<T> getGrandParent() {
449458
return (RedBlackNode<T>) parent.parent;
450459
}
451460

452-
protected RedBlackNode<T> getUncle() {
453-
RedBlackNode<T> grandParent = getGrandParent();
461+
protected RedBlackNode<T> getUncle(RedBlackNode<T> grandParent) {
454462
if (grandParent == null) return null;
455-
if (grandParent.lesser != null && grandParent.lesser.equals(parent)) {
463+
if (grandParent.lesser != null && grandParent.lesser == parent) {
456464
return (RedBlackNode<T>) grandParent.greater;
457-
} else if (grandParent.greater != null && grandParent.greater.equals(parent)) {
465+
} else if (grandParent.greater != null && grandParent.greater == parent) {
458466
return (RedBlackNode<T>) grandParent.lesser;
459467
}
460468
return null;
461469
}
462470

471+
protected RedBlackNode<T> getUncle() {
472+
RedBlackNode<T> grandParent = getGrandParent();
473+
return getUncle(grandParent);
474+
}
475+
463476
protected RedBlackNode<T> getSibling() {
464477
if (parent == null) return null;
465478
if (parent.lesser.equals(this)) {

0 commit comments

Comments
 (0)