1
- using System ;
1
+ using DataStructures . Common ;
2
+ using System ;
2
3
using System . Collections . Generic ;
3
4
4
- using DataStructures . Common ;
5
-
6
5
namespace DataStructures . Trees
7
6
{
8
7
/// <summary>
@@ -14,7 +13,6 @@ public enum RedBlackTreeColors
14
13
Black = 1
15
14
} ;
16
15
17
-
18
16
/// <summary>
19
17
/// Red-Black Tree Data Structure.
20
18
/// </summary>
@@ -29,6 +27,10 @@ public class RedBlackTree<TKey> : BinarySearchTree<TKey> where TKey : IComparabl
29
27
internal set { base . Root = value ; }
30
28
}
31
29
30
+ private bool IsRoot ( RedBlackTreeNode < TKey > node )
31
+ {
32
+ return node == this . Root ;
33
+ }
32
34
33
35
/// <summary>
34
36
/// CONSTRUCTOR.
@@ -233,8 +235,8 @@ protected virtual void _adjustTreeAfterInsertion(RedBlackTreeNode<TKey> currentN
233
235
// This is the simplest step: Basically recolor, and bubble up to see if more work is needed.
234
236
if ( _safeCheckIsRed ( _safeGetSibling ( currentNode . Parent ) ) )
235
237
{
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 ;
238
240
239
241
// Color sibling of parent as black
240
242
_safeUpdateColor ( _safeGetSibling ( currentNode . Parent ) , RedBlackTreeColors . Black ) ;
@@ -455,80 +457,109 @@ protected override bool _remove(BSTNode<TKey> nodeToDelete)
455
457
}
456
458
457
459
/// <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.
461
463
/// </summary>
462
464
protected bool _remove ( RedBlackTreeNode < TKey > nodeToDelete )
463
465
{
464
466
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 )
472
467
{
473
- node1 = nodeToDelete ;
474
- }
475
- else
476
- {
477
- // nodeToDelete has two children
478
- node1 = ( RedBlackTreeNode < TKey > ) base . _findNextLarger ( nodeToDelete ) ;
468
+ return false ;
479
469
}
480
470
481
- // Left child case
482
- if ( node1 . HasLeftChild )
471
+ if ( IsRoot ( nodeToDelete ) && ! nodeToDelete . HasChildren )
483
472
{
484
- node2 = node1 . LeftChild ;
473
+ Root = null ;
485
474
}
486
475
else
487
476
{
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 ;
494
479
495
- if ( node1 . Parent != null )
496
- {
497
- if ( node1 . IsLeftChild )
480
+ if ( ! nodeToDelete . HasChildren )
498
481
{
499
- node1 . Parent . LeftChild = node2 ;
482
+ x = nodeToDelete ;
483
+ Transplant ( nodeToDelete , null ) ;
500
484
}
501
- else
485
+ else if ( nodeToDelete . HasOnlyRightChild )
502
486
{
503
- node1 . Parent . RightChild = node2 ;
487
+ x = nodeToDelete . RightChild ;
488
+ Transplant ( nodeToDelete , nodeToDelete . RightChild ) ;
504
489
}
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 ;
511
500
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
+ }
517
514
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
+ }
523
531
}
524
532
525
- // Decrement the count
526
533
base . _count -- ;
527
534
528
535
return true ;
529
536
}
530
537
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
+ }
531
557
558
+ if ( replacement != null )
559
+ {
560
+ replacement . Parent = replaced . Parent ;
561
+ }
562
+ }
532
563
/*************************************************************************************************/
533
564
534
565
@@ -629,7 +660,5 @@ public override void RemoveMax()
629
660
// Invoke the internal remove node method.
630
661
this . _remove ( node ) ;
631
662
}
632
-
633
663
}
634
-
635
664
}
0 commit comments