1- using System ;
1+ using DataStructures . Common ;
2+ using System ;
23using System . Collections . Generic ;
34
4- using DataStructures . Common ;
5-
65namespace DataStructures . Trees
76{
87 /// <summary>
@@ -14,7 +13,6 @@ public enum RedBlackTreeColors
1413 Black = 1
1514 } ;
1615
17-
1816 /// <summary>
1917 /// Red-Black Tree Data Structure.
2018 /// </summary>
@@ -29,6 +27,10 @@ public class RedBlackTree<TKey> : BinarySearchTree<TKey> where TKey : IComparabl
2927 internal set { base . Root = value ; }
3028 }
3129
30+ private bool IsRoot ( RedBlackTreeNode < TKey > node )
31+ {
32+ return node == this . Root ;
33+ }
3234
3335 /// <summary>
3436 /// CONSTRUCTOR.
@@ -233,8 +235,8 @@ protected virtual void _adjustTreeAfterInsertion(RedBlackTreeNode<TKey> currentN
233235 // This is the simplest step: Basically recolor, and bubble up to see if more work is needed.
234236 if ( _safeCheckIsRed ( _safeGetSibling ( currentNode . Parent ) ) )
235237 {
236- // If it has a sibling and it is red , then then it has a parent
237- currentNode . Parent . Color = RedBlackTreeColors . Red ;
238+ // If it has a sibling and it is black , then then it has a parent
239+ currentNode . Parent . Color = RedBlackTreeColors . Black ;
238240
239241 // Color sibling of parent as black
240242 _safeUpdateColor ( _safeGetSibling ( currentNode . Parent ) , RedBlackTreeColors . Black ) ;
@@ -455,80 +457,109 @@ protected override bool _remove(BSTNode<TKey> nodeToDelete)
455457 }
456458
457459 /// <summary>
458- /// The internal remove helper.
459- /// Separated from the overriden version to avoid casting the objects from BSTNode to RedBlackTreeNode.
460- /// This is called from the overriden _remove(BSTNode nodeToDelete) helper.
460+ /// The internal remove helper.
461+ /// Separated from the overriden version to avoid casting the objects from BSTNode to RedBlackTreeNode.
462+ /// This is called from the overriden _remove(BSTNode nodeToDelete) helper.
461463 /// </summary>
462464 protected bool _remove ( RedBlackTreeNode < TKey > nodeToDelete )
463465 {
464466 if ( nodeToDelete == null )
465- return false ;
466-
467- // Temporary nodes
468- RedBlackTreeNode < TKey > node1 , node2 ;
469-
470- // If nodeToDelete has either one child or no children at all
471- if ( ! nodeToDelete . HasLeftChild || ! nodeToDelete . HasRightChild )
472467 {
473- node1 = nodeToDelete ;
474- }
475- else
476- {
477- // nodeToDelete has two children
478- node1 = ( RedBlackTreeNode < TKey > ) base . _findNextLarger ( nodeToDelete ) ;
468+ return false ;
479469 }
480470
481- // Left child case
482- if ( node1 . HasLeftChild )
471+ if ( IsRoot ( nodeToDelete ) && ! nodeToDelete . HasChildren )
483472 {
484- node2 = node1 . LeftChild ;
473+ Root = null ;
485474 }
486475 else
487476 {
488- node2 = node1 . RightChild ;
489- }
490-
491- // If node2 is not null, copy parent references
492- if ( node2 != null )
493- node2 . Parent = node1 . Parent ;
477+ // X is the node we will replace with the nodeToDelete in the tree once we remove it.
478+ RedBlackTreeNode < TKey > x ;
494479
495- if ( node1 . Parent != null )
496- {
497- if ( node1 . IsLeftChild )
480+ if ( ! nodeToDelete . HasChildren )
498481 {
499- node1 . Parent . LeftChild = node2 ;
482+ x = nodeToDelete ;
483+ Transplant ( nodeToDelete , null ) ;
500484 }
501- else
485+ else if ( nodeToDelete . HasOnlyRightChild )
502486 {
503- node1 . Parent . RightChild = node2 ;
487+ x = nodeToDelete . RightChild ;
488+ Transplant ( nodeToDelete , nodeToDelete . RightChild ) ;
504489 }
505- }
506- else
507- {
508- Root = node2 ;
509- Root . Parent = null ;
510- }
490+ else if ( nodeToDelete . HasOnlyLeftChild )
491+ {
492+ x = nodeToDelete . LeftChild ;
493+ Transplant ( nodeToDelete , nodeToDelete . LeftChild ) ;
494+ }
495+ else
496+ {
497+ // Y is the node we will replace with the X in the tree once we move it to the nodeToDelete position.
498+ var y = ( RedBlackTreeNode < TKey > ) _findMinNode ( nodeToDelete . RightChild ) ;
499+ x = y . RightChild ;
511500
512- // Swap values
513- if ( ! node1 . IsEqualTo ( nodeToDelete ) )
514- {
515- nodeToDelete . Value = node1 . Value ;
516- }
501+ if ( y . Parent == nodeToDelete )
502+ {
503+ if ( x != null )
504+ {
505+ x . Parent = y ;
506+ }
507+ }
508+ else
509+ {
510+ Transplant ( y , y . RightChild ) ;
511+ y . RightChild = nodeToDelete . RightChild ;
512+ y . RightChild . Parent = y ;
513+ }
517514
518- // Adjust the Red-Black Tree rules
519- if ( node1 . Color == RedBlackTreeColors . Black && node2 != null )
520- {
521- _adjustTreeAfterRemoval ( node2 ) ;
522- Root . Color = RedBlackTreeColors . Black ;
515+ Transplant ( nodeToDelete , y ) ;
516+ y . LeftChild = nodeToDelete . LeftChild ;
517+ y . LeftChild . Parent = y ;
518+ y . Color = nodeToDelete . Color ;
519+
520+ if ( Root == nodeToDelete )
521+ {
522+ Root = y ;
523+ Root . Parent = null ;
524+ }
525+ }
526+
527+ if ( nodeToDelete . Color == RedBlackTreeColors . Black )
528+ {
529+ _adjustTreeAfterRemoval ( x ) ;
530+ }
523531 }
524532
525- // Decrement the count
526533 base . _count -- ;
527534
528535 return true ;
529536 }
530537
538+ /// <summary>
539+ /// Insert one subtree in the place of the other in his parent.
540+ /// </summary>
541+ /// <param name="replaced">Subtree of node will be replaced by <param name="replacement">.</param></param>
542+ /// <param name="replacement">Subtree replaces <param name="replaced">.</param></param>
543+ private void Transplant ( RedBlackTreeNode < TKey > replaced , RedBlackTreeNode < TKey > replacement )
544+ {
545+ if ( replaced . Parent == null )
546+ {
547+ this . Root = replacement ;
548+ }
549+ else if ( replaced == replaced . Parent . LeftChild )
550+ {
551+ replaced . Parent . LeftChild = replacement ;
552+ }
553+ else
554+ {
555+ replaced . Parent . RightChild = replacement ;
556+ }
531557
558+ if ( replacement != null )
559+ {
560+ replacement . Parent = replaced . Parent ;
561+ }
562+ }
532563 /*************************************************************************************************/
533564
534565
@@ -629,7 +660,5 @@ public override void RemoveMax()
629660 // Invoke the internal remove node method.
630661 this . _remove ( node ) ;
631662 }
632-
633663 }
634-
635664}
0 commit comments