@@ -46,6 +46,22 @@ public void Clear()
4646 {
4747 root = null ;
4848 }
49+
50+ public T FindMin ( )
51+ {
52+ if ( root == null )
53+ throw new ApplicationException ( "FindMin called on empty BinSearchTree" ) ;
54+ else
55+ return FindMin ( root ) ;
56+ }
57+ private T FindMin ( Node nodeP )
58+ {
59+ if ( nodeP . left == null )
60+ return nodeP . Data ;
61+ else
62+ return FindMin ( nodeP . left ) ;
63+ }
64+
4965 private int GetHeight ( Node nodeP )
5066 {
5167 if ( nodeP == null )
@@ -68,13 +84,17 @@ private int UpdateHeight(Node nodeP)
6884 return height ;
6985 }
7086
71- //
7287 private int SubtreeBalance ( Node nodeP )
7388 {
7489 // Will return
7590 // a negative number if subtree is right-heavy
7691 // a positive number if subtree is left-heavy
7792 // 0 if the subtree is perfectly balanced.
93+ // The AVL tree will need to be re-balanced if the value
94+ // returned is greater than or equal to 2, or
95+ // less than or equal to -2.
96+ // Stated differently, if the value returned is
97+ // -1, 0 or 1, then no re-balancing will take place.
7898 UpdateHeight ( nodeP . left ) ;
7999 UpdateHeight ( nodeP . right ) ;
80100 int balance ;
@@ -88,7 +108,7 @@ private int SubtreeBalance(Node nodeP)
88108 }
89109 else if ( nodeP . left == null )
90110 {
91- balance = - ( nodeP . right . Height + 1 ) ; // right side heavy represented by negative number
111+ balance = - ( nodeP . right . Height + 1 ) ;
92112 }
93113 else if ( nodeP . right == null )
94114 {
@@ -294,6 +314,70 @@ private int Depth(Node nodeP, int depth)
294314 return result ;
295315 }
296316
317+ public bool Remove ( T value )
318+ {
319+ return Remove ( value , ref root ) ;
320+ }
321+
322+ private bool Remove ( T value , ref Node nodeP )
323+ {
324+ bool found = false ;
325+ if ( nodeP != null )
326+ {
327+ if ( value . CompareTo ( nodeP . Data ) < 0 ) // value < nodeP.Data, check left subtree
328+ {
329+ found = Remove ( value , ref nodeP . left ) ; // similar to BST's find and remove method
330+ if ( SubtreeBalance ( nodeP ) <= - 2 ) // negative balance means heavy on right side
331+ {
332+ if ( SubtreeBalance ( nodeP . right ) <= 0 ) // children in straight line
333+ nodeP = RotaterightChild ( nodeP ) ; // rotate middle up to balance
334+ else
335+ nodeP = DoublerightChild ( nodeP ) ; // children in zig patter - needs double rotate to balance
336+ }
337+ }
338+ else if ( value . CompareTo ( nodeP . Data ) > 0 ) // value > nodeP.Data, check right subtree
339+ {
340+ found = Remove ( value , ref nodeP . right ) ;
341+ if ( SubtreeBalance ( nodeP ) >= 2 )
342+ {
343+ if ( SubtreeBalance ( nodeP . left ) >= 0 )
344+ nodeP = RotateleftChild ( nodeP ) ;
345+ else
346+ nodeP = DoubleleftChild ( nodeP ) ;
347+ }
348+ }
349+ else // The value was found!
350+ {
351+ found = true ;
352+ if ( nodeP . left != null && nodeP . right != null ) // Two children
353+ {
354+ nodeP . Data = FindMin ( nodeP . right ) ;
355+ Remove ( nodeP . Data , ref nodeP . right ) ;
356+ if ( SubtreeBalance ( nodeP ) == 2 ) // Need to rebalance
357+ {
358+ if ( SubtreeBalance ( nodeP . left ) >= 0 )
359+ nodeP = RotateleftChild ( nodeP ) ;
360+ else
361+ nodeP = DoubleleftChild ( nodeP ) ;
362+ }
363+
364+ }
365+ else
366+ {
367+ nodeP = nodeP . left ?? nodeP . right ; // replace with one or no child
368+ // This is equivalent to
369+ // if (nodeP.left == null){
370+ // nodeP = nodeP.right;
371+ // } else { nodeP = nodeP.left;}
372+ // Observe that if both are null, then nodeP simply
373+ // becomes null, as expected.
374+ }
375+ }
376+ }
377+ return found ;
378+ }
379+
380+
297381 // The ToString method is simply here to help us debug.
298382 // It is not really pretty, but using pre-order and spaces
299383 // to make it easier to understand how the tree is
0 commit comments