Skip to content

Commit d00ea38

Browse files
Fix red black tree for remove one and only element from tree.
1 parent aa356a8 commit d00ea38

File tree

2 files changed

+61
-35
lines changed

2 files changed

+61
-35
lines changed

DataStructures/Trees/RedBlackTree.cs

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -465,54 +465,61 @@ protected bool _remove(RedBlackTreeNode<TKey> nodeToDelete)
465465
return false;
466466
}
467467

468-
// X it's node that will become move to original nodeToDelete position in the tree.
469-
RedBlackTreeNode<TKey> x;
470-
471-
if (nodeToDelete.HasOnlyRightChild)
472-
{
473-
x = nodeToDelete.RightChild;
474-
Transplant(nodeToDelete, nodeToDelete.RightChild);
475-
}
476-
else if (nodeToDelete.HasOnlyLeftChild)
468+
if (!nodeToDelete.HasChildren)
477469
{
478-
x = nodeToDelete.LeftChild;
479-
Transplant(nodeToDelete, nodeToDelete.LeftChild);
470+
Root = null;
480471
}
481472
else
482473
{
483-
// Y it's node that will become move to original X position in the tree.
484-
var y = (RedBlackTreeNode<TKey>)_findMinNode(nodeToDelete.RightChild);
485-
x = y.RightChild;
474+
// X it's node that will become move to original nodeToDelete position in the tree.
475+
RedBlackTreeNode<TKey> x;
486476

487-
if (y.Parent == nodeToDelete)
477+
if (nodeToDelete.HasOnlyRightChild)
488478
{
489-
if (x != null)
490-
{
491-
x.Parent = y;
492-
}
479+
x = nodeToDelete.RightChild;
480+
Transplant(nodeToDelete, nodeToDelete.RightChild);
493481
}
494-
else
482+
else if (nodeToDelete.HasOnlyLeftChild)
495483
{
496-
Transplant(y, y.RightChild);
497-
y.RightChild = nodeToDelete.RightChild;
498-
y.RightChild.Parent = y;
484+
x = nodeToDelete.LeftChild;
485+
Transplant(nodeToDelete, nodeToDelete.LeftChild);
499486
}
487+
else
488+
{
489+
// Y it's node that will become move to original X position in the tree.
490+
var y = (RedBlackTreeNode<TKey>) _findMinNode(nodeToDelete.RightChild);
491+
x = y.RightChild;
500492

501-
Transplant(nodeToDelete, y);
502-
y.LeftChild = nodeToDelete.LeftChild;
503-
y.LeftChild.Parent = y;
504-
y.Color = nodeToDelete.Color;
493+
if (y.Parent == nodeToDelete)
494+
{
495+
if (x != null)
496+
{
497+
x.Parent = y;
498+
}
499+
}
500+
else
501+
{
502+
Transplant(y, y.RightChild);
503+
y.RightChild = nodeToDelete.RightChild;
504+
y.RightChild.Parent = y;
505+
}
505506

506-
if (Root == nodeToDelete)
507-
{
508-
Root = y;
509-
Root.Parent = null;
507+
Transplant(nodeToDelete, y);
508+
y.LeftChild = nodeToDelete.LeftChild;
509+
y.LeftChild.Parent = y;
510+
y.Color = nodeToDelete.Color;
511+
512+
if (Root == nodeToDelete)
513+
{
514+
Root = y;
515+
Root.Parent = null;
516+
}
510517
}
511-
}
512518

513-
if (nodeToDelete.Color == RedBlackTreeColors.Black)
514-
{
515-
_adjustTreeAfterRemoval(x);
519+
if (nodeToDelete.Color == RedBlackTreeColors.Black)
520+
{
521+
_adjustTreeAfterRemoval(x);
522+
}
516523
}
517524

518525
base._count--;

UnitTest/DataStructuresTests/RedBlackTreeTest.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,25 @@ public void Remove_ThrowExceptionWhenTryRemoveNonExistentNode()
374374
//TODO Create more specyfic exception type for this kind of errors, with inheritance from ArgumentException.
375375
Assert.Throws<Exception>(() =>redBlackTree.Remove(999));
376376
}
377+
378+
[Fact]
379+
public void Remove_OneAndOnlyTreeNode()
380+
{
381+
var oneElementTree = new RedBlackTree<int>();
382+
Assert.Equal(0, oneElementTree.Count);
383+
Assert.Null(oneElementTree.Root);
384+
Assert.True(oneElementTree.IsEmpty);
385+
386+
oneElementTree.Insert(1);
387+
Assert.Equal(1, oneElementTree.Count);
388+
Assert.NotNull(oneElementTree.Root);
389+
Assert.False(oneElementTree.IsEmpty);
390+
391+
oneElementTree.Remove(1);
392+
Assert.Equal(0, oneElementTree.Count);
393+
Assert.Null(oneElementTree.Root);
394+
Assert.True(oneElementTree.IsEmpty);
395+
}
377396
}
378397

379398
/// <summary>

0 commit comments

Comments
 (0)