Skip to content

Commit 92f0cbb

Browse files
author
phishman3579
committed
Caught a bug in the red-black tree implementation
git-svn-id: https://java-algorithms-implementation.googlecode.com/svn/trunk@415 032fbc0f-8cab-eb90-e552-f08422b9a96a
1 parent 7f4eb13 commit 92f0cbb

File tree

1 file changed

+44
-49
lines changed

1 file changed

+44
-49
lines changed

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

+44-49
Original file line numberDiff line numberDiff line change
@@ -209,28 +209,26 @@ protected void removeNode(Node<T> node) {
209209
if (lesser.id != null && greater.id != null) {
210210
// Two children
211211
RedBlackNode<T> greatestInLesser = (RedBlackNode<T>) this.getGreatest(lesser);
212-
if (greatestInLesser == null || greatestInLesser.id == null)
213-
greatestInLesser = lesser;
212+
if (greatestInLesser == null || greatestInLesser.id == null) greatestInLesser = lesser;
214213
// Replace node with greatest in his lesser tree, which leaves
215214
// us with only one child
216215
replaceValueOnly(nodeRemoved, greatestInLesser);
217216
nodeRemoved = greatestInLesser;
218217
}
219218

220219
// Handle one child
221-
RedBlackNode<T> child = (RedBlackNode<T>) ((nodeRemoved.lesser.id != null) ? nodeRemoved.lesser
222-
: nodeRemoved.greater);
220+
RedBlackNode<T> child = (RedBlackNode<T>) ((nodeRemoved.lesser.id != null) ? nodeRemoved.lesser : nodeRemoved.greater);
223221
if (nodeRemoved.color == BLACK) {
224-
if (child.color == BLACK) {
225-
nodeRemoved.color = RED;
226-
}
222+
if (child.color == BLACK) nodeRemoved.color = RED;
227223
boolean result = balanceAfterDelete(nodeRemoved);
228224
if (!result) return;
229225
}
230226
replaceWithChild(nodeRemoved, child);
231-
if (root.equals(nodeRemoved) && nodeRemoved.isLeaf()) {
227+
if (root.equals(nodeRemoved)) {
228+
root.parent = null;
229+
((RedBlackNode<T>)root).color = BLACK;
232230
// If we replaced the root with a leaf, just null out root
233-
root = null;
231+
if (nodeRemoved.isLeaf()) root = null;
234232
}
235233
}
236234

@@ -263,12 +261,11 @@ private void replaceWithChild(RedBlackNode<T> nodeToReplace, RedBlackNode<T> nod
263261
nodeToReplace.id = nodeToReplaceWith.id;
264262
nodeToReplace.color = nodeToReplaceWith.color;
265263

266-
// root should always be black
267-
if (nodeToReplace.parent == null)
268-
nodeToReplace.color = BLACK;
269-
270264
nodeToReplace.lesser = nodeToReplaceWith.lesser;
265+
if (nodeToReplace.lesser!=null) nodeToReplace.lesser.parent = nodeToReplace;
266+
271267
nodeToReplace.greater = nodeToReplaceWith.greater;
268+
if (nodeToReplace.greater!=null) nodeToReplace.greater.parent = nodeToReplace;
272269
}
273270

274271
/**
@@ -306,34 +303,40 @@ private boolean balanceAfterDelete(RedBlackNode<T> node) {
306303
}
307304
}
308305

309-
if (parent.color == BLACK && sibling.color == BLACK && ((RedBlackNode<T>) sibling.lesser).color == BLACK
310-
&& ((RedBlackNode<T>) sibling.greater).color == BLACK) {
306+
if (parent.color == BLACK && sibling.color == BLACK
307+
&& ((RedBlackNode<T>) sibling.lesser).color == BLACK
308+
&& ((RedBlackNode<T>) sibling.greater).color == BLACK
309+
) {
311310
// Case 3 - parent, sibling, and sibling's children are black.
312311
sibling.color = RED;
313312
boolean result = balanceAfterDelete(parent);
314-
if (!result)
315-
return false;
316-
} else if (parent.color == RED && sibling.color == BLACK && ((RedBlackNode<T>) sibling.lesser).color == BLACK
317-
&& ((RedBlackNode<T>) sibling.greater).color == BLACK) {
318-
// Case 4 - sibling and sibling's children are black, but parent is
319-
// red.
313+
if (!result) return false;
314+
} else if (parent.color == RED && sibling.color == BLACK
315+
&& ((RedBlackNode<T>) sibling.lesser).color == BLACK
316+
&& ((RedBlackNode<T>) sibling.greater).color == BLACK
317+
) {
318+
// Case 4 - sibling and sibling's children are black, but parent is red.
320319
sibling.color = RED;
321320
parent.color = BLACK;
322321
} else {
323322
if (sibling.color == BLACK) {
324323
// Case 5 - sibling is black, sibling's left child is red,
325324
// sibling's right child is black, and node is the left child of
326325
// its parent.
327-
if (node.equals(parent.lesser) && ((RedBlackNode<T>) sibling.lesser).color == RED
328-
&& ((RedBlackNode<T>) sibling.greater).color == BLACK) {
326+
if (node.equals(parent.lesser)
327+
&& ((RedBlackNode<T>) sibling.lesser).color == RED
328+
&& ((RedBlackNode<T>) sibling.greater).color == BLACK
329+
) {
329330
sibling.color = RED;
330331
((RedBlackNode<T>) sibling.lesser).color = RED;
331332
rotateRight(sibling);
332333
// Rotation, need to update parent/sibling
333334
parent = (RedBlackNode<T>) node.parent;
334335
sibling = node.getSibling();
335-
} else if (node.equals(parent.greater) && ((RedBlackNode<T>) sibling.lesser).color == BLACK
336-
&& ((RedBlackNode<T>) sibling.greater).color == RED) {
336+
} else if (node.equals(parent.greater)
337+
&& ((RedBlackNode<T>) sibling.lesser).color == BLACK
338+
&& ((RedBlackNode<T>) sibling.greater).color == RED
339+
) {
337340
sibling.color = RED;
338341
((RedBlackNode<T>) sibling.greater).color = RED;
339342
rotateLeft(sibling);
@@ -393,32 +396,26 @@ protected boolean validateNode(Node<T> node) {
393396

394397
if (rbNode.color == RED) {
395398
// You should not have two red nodes in a row
396-
if (lesser.color == RED)
397-
return false;
398-
if (greater.color == RED)
399-
return false;
399+
if (lesser.color == RED) return false;
400+
if (greater.color == RED) return false;
400401
}
401402

402403
if (!lesser.isLeaf()) {
403404
// Check BST property
404405
boolean lesserCheck = lesser.id.compareTo(rbNode.id) <= 0;
405-
if (!lesserCheck)
406-
return false;
406+
if (!lesserCheck) return false;
407407
// Check red-black property
408408
lesserCheck = this.validateNode(lesser);
409-
if (!lesserCheck)
410-
return false;
409+
if (!lesserCheck) return false;
411410
}
412411

413412
if (!greater.isLeaf()) {
414413
// Check BST property
415414
boolean greaterCheck = greater.id.compareTo(rbNode.id) > 0;
416-
if (!greaterCheck)
417-
return false;
415+
if (!greaterCheck) return false;
418416
// Check red-black property
419417
greaterCheck = this.validateNode(greater);
420-
if (!greaterCheck)
421-
return false;
418+
if (!greaterCheck) return false;
422419
}
423420

424421
return true;
@@ -458,15 +455,13 @@ protected RedBlackNode(Node<T> parent, T id, boolean color) {
458455
}
459456

460457
protected RedBlackNode<T> getGrandParent() {
461-
if (parent == null || parent.parent == null)
462-
return null;
458+
if (parent == null || parent.parent == null) return null;
463459
return (RedBlackNode<T>) parent.parent;
464460
}
465461

466462
protected RedBlackNode<T> getUncle() {
467463
RedBlackNode<T> grandParent = getGrandParent();
468-
if (grandParent == null)
469-
return null;
464+
if (grandParent == null) return null;
470465
if (grandParent.lesser != null && grandParent.lesser.equals(parent)) {
471466
return (RedBlackNode<T>) grandParent.greater;
472467
} else if (grandParent.greater != null && grandParent.greater.equals(parent)) {
@@ -476,8 +471,7 @@ protected RedBlackNode<T> getUncle() {
476471
}
477472

478473
protected RedBlackNode<T> getSibling() {
479-
if (parent == null)
480-
return null;
474+
if (parent == null) return null;
481475
if (parent.lesser.equals(this)) {
482476
return (RedBlackNode<T>) parent.greater;
483477
} else if (parent.greater.equals(this)) {
@@ -489,10 +483,8 @@ protected RedBlackNode<T> getSibling() {
489483
}
490484

491485
protected boolean isLeaf() {
492-
if (lesser != null)
493-
return false;
494-
if (greater != null)
495-
return false;
486+
if (lesser != null) return false;
487+
if (greater != null) return false;
496488
return true;
497489
}
498490

@@ -524,8 +516,11 @@ public static <T extends Comparable<T>> String getString(RedBlackNode<T> node) {
524516
private static <T extends Comparable<T>> String getString(RedBlackNode<T> node, String prefix, boolean isTail) {
525517
StringBuilder builder = new StringBuilder();
526518

527-
builder.append(prefix + (isTail ? "└── " : "├── ") + "(" + ((node.color == RED) ? "RED" : "BLACK") + ") "
528-
+ node.id + "\n");
519+
builder.append(prefix + (isTail ? "└── " : "├── ") + "(" + ((node.color == RED) ? "RED" : "BLACK") + ") " + node.id
520+
+ " [parent=" + ((node.parent!=null)?node.parent.id:"NULL")
521+
+ " grand-parent=" + ((node.parent!=null && node.parent.parent!=null)?node.parent.parent.id:"NULL")
522+
+ "]\n"
523+
);
529524
List<Node<T>> children = null;
530525
if (node.lesser != null || node.greater != null) {
531526
children = new ArrayList<Node<T>>(2);

0 commit comments

Comments
 (0)