### Deleting a node from a BST --- Part 2 (the hard case)

• Pre-discussion of case 3: deletion node has two subtrees

• Deleting a node that has two subtrees is very complicated....

Here is the summary of the procedure:

 First, we find the deletion node p (= the node that we want to delete) Find the successor node of p Replace the content of node p with the content of the successor node Delete the successor node

Before we can discuss the deletion algorithm, we must discuss how to find the successor node first....

• Finding the successor node

• Successor node:

 Successor node = the node in the right subtree that has the minimum value

• Recall: how to find the minimum value in a BST

• The node with the minimum value in a (sub)tree is found by:

 Follow the left child in each branch until you reach a node that does not have a left child

Examples:

• Let us work out some deletion examples first before discussing the delete algorithm

• Deleting a node with 2 subtrees: illustrating the algorithm with examples

• Example 1:

• Delete node 9 in the following BST:

• First, we must find the node with the value 9:

(We use the variable p to point to the deletion node)

• Next, we find the successor node of the node 9.

The successor node is the node with the minimum value in the right subtree:

• We copy the content of the successor node of the node into the deletion node (p):

• The last step is deleting the successor node from the BST:

Notice that the tree satisfies the Binary Search Tree property:

 all nodes in left subtree has smaller values and all nodes in the right subtree has larger values.

• Example 2:

• Delete node 6 in the following BST:

• First, we must find the node with the value 6:

(We use the variable p to point to the deletion node)

• Next, we find the successor node of the node 6.

The successor node is the node with the minimum value in the right subtree:

• We copy the content of the successor node of the node into the deletion node (p):

• The last step is deleting the successor node from the BST:

Because the successor node does not have a left subtree, we can delete the successor node using the short-circuit method (of Case 2)

Result:

Notice that the tree satisfies the Binary Search Tree property:

 all nodes in left subtree has smaller values and all nodes in the right subtree has larger values.

• Delete a node with 2 subtrees --- pseudo code (almost Java code)

 ``` /* =================================== Step 1: Find the deletion node =================================== */ p = findNode(x); // Find the node that contains the value x // ===> p is the "deletion node" /* ========================================================= Step 2: Find the successor node in the RIGHT subtree of p ========================================================= */ succ = p.right; // Starting point: right subtree while ( succ.left != null ) { succ = succ.left; // Always go left to find min. value } /* =================================================== Step 3: replace content of p with successor node =================================================== */ p.value = succ.value; /* =================================================== Step 4: delete successor node =================================================== */ succ's Parent.left = succ.right; // Trouble: we need "succ's Parent" !!! ```

We can use the 2 consecutive nodes pointers trick used in Linked list (see: click here ) to find "succ's Parent" node...

• Delete a node with 2 subtrees --- Java code

 ``` /* =================================== Step 1: Find the deletion node =================================== */ p = findNode(x); // Find the node that contains the value x // ===> p is the "deletion node" /* ========================================================= Step 2: Find the successor node in the RIGHT subtree of p ========================================================= */ succ = p.right; // Starting point: right subtree succParent = p; // succParent points to prev. node in BST while ( succ.left != null ) { succParent = succ; // Track succ's parent ! succ = succ.left; // Always go left to find min. value } /* =================================================== Step 3: replace content of p with successor node =================================================== */ p.value = succ.value; /* =================================================== Step 4: delete successor node =================================================== */ succParent.left = succ.right; // Now we have "succ's Parent" !!! ```

• We are not yet done: there is one special situation in case 3 !!!

• There is one special situation that we need to take care of in case 3:

 The right tree of the deletion node does not have a left branch

• Example 2:

• Delete node 6 in the following BST:

• First, we must find the node with the value 6:

(We use the variable p to point to the deletion node)

• In the special situtaion, the right subtree does not have a left branch:

The minimum value is the root node of the right subtree !

• We will still copy the content of the successor node of the node into the deletion node (p):

• The difference is: we must short-circuit the root node of the subtree:

using the statement:

 ``` p.right = succ.right; ```

Result:

Notice that the tree satisfies the Binary Search Tree property:

 all nodes in left subtree has smaller values and all nodes in the right subtree has larger values.

• How to detect the special situation:

 ``` succ = p.right; // start at the right subtree if ( succ.left == null ) { // Right subtree has NO left branch .... (handle the special case) } ```

• Case 3: deleting a node with 2 subtrees

• Here is finally the algorithm to delete a node with 2 subtrees:

 ``` /* =================================== Step 1: Find the deletion node =================================== */ p = findNode(x); // Find the node that contains the value x // ===> p is the "deletion node" succ = p.right; // Starting point: right subtree succParent = p; // succParent points to prev. node in BST /* ========================================= Take care of the special case ========================================= */ if ( succ.left == null ) // Special case detected ! { p.value = succ.value; // Replace p value p.right = succ.right; // Replace p right subtree return; // Done } /* ========================================================= Step 2: Find the successor node in the RIGHT subtree of p ========================================================= */ while ( succ.left != null ) { succParent = succ; // Track succ's parent ! succ = succ.left; // Always go left to find min. value } /* =================================================== Step 3: replace content of p with successor node =================================================== */ p.value = succ.value; /* =================================================== Step 4: delete successor node =================================================== */ succParent.left = succ.right; // Now we have "succ's Parent" !!! ```

• The Hibbard node deletion algorithm

• Pseudo code of the remove(k) algorithm:

 ``` if ( k not in BST ) { return; // Nothing to delete } /****** The "Hibbard deletion algorithm" ******/ if ( k has no subtrees ) // x x { // / \ ==> / unlink k from k's parent; // y k y return; // } if ( k has 1 tree ) // x x { // / \ ==> / \ make k's parent point to k's subtree; // y k y z return; // \ } z /* k has 2 subtrees - TOUGH */ (1) find the successor of k: go right once go left all the way down (2) Replace k with k's successor; (3) Make the successor's parent point to the successor's right subtree; ```

• Java code:

 ``` /* ======================================================= remove(x): delete node containg search value x ======================================================= */ public void remove(double x) { Node p; // Help variable Node parent; // parent node Node succ; // successor node /* -------------------------------------------- Find the node with search value == "x" in the BST -------------------------------------------- */ p = findNode(x); if ( p == null ) return; // Not found ==> nothing to delete.... /* ======================================================== Hibbard's Algorithm ======================================================== */ /* ============================================= Handel case 1: p has no children nodes ============================================= */ if ( p.left == null && p.right == null ) // Case 1: p has no children { if ( p == root ) // Special case... { root = null; return; } parent = myParent; // myParent was set by findNode(x).... /* -------------------------------- Delete p from p's parent -------------------------------- */ if ( parent.left == p ) parent.left = null; else parent.right = null; return; } /* ----------------------------------------------------------- If program reach here, we know that: at least ONE of p.left or p.right is NOT null I.e.: p has at least 1 child node ------------------------------------------------------------ */ /* =========================================================== Handle case 2: p has 1 child node =========================================================== */ if ( p.right == null ) // If true: p.left ≠ null, p has left child { if ( p == root ) // Special case { root = root.left; return; } parent = myParent; // myParent was set by findNode(x).... /* ---------------------------------------------- Link p's left child as p's parent child ---------------------------------------------- */ if ( parent.left == p ) parent.left = p.left; else parent.right = p.left; return; } if ( p.left == null ) // If true: p.right ≠ null, p has right child { if ( p == root ) // Special case { root = root.right; return; } parent = myParent; // myParent was set by findNode(x).... /* ---------------------------------------------- Link p's right child as p's parent child ---------------------------------------------- */ if ( parent.left == p ) parent.left = p.right; else parent.right = p.right; return; } /* ================================================================ Handle case 3: node has 2 children - find successor of p succ(p) is as as follows: 1 step right, all the way left Note: succ(p) has NOT left child ! ================================================================ */ if ( p.right.left == null ) { /* ====================================================== Special case: the right node of p IS the successor ! Replace p with p.right ====================================================== */ p.value = p.right.value; // Replace p value p.right = p.right.right; // Replace p right subtree return; // Done } succ = p.right; // Go RIGHT once Node succParent = p; // We must also know succ's parent ! /* ---------------------------------- Find the successor node of node p and successor's parent node --------------------------------- */ while ( succ.left != null ) { succParent = succ; // Track succ's parent succ = succ.left; } /* ------------------------------ Now we can delete p ! ------------------------------ */ p.value = succ.value; // Replace p with successor info. succParent.left = succ.right; // Link right tree to parent's left } ```

• Test program:

 ``` public static void main(String[] args) { Scanner in = new Scanner(System.in); BST x = new BST(); // Create an empty BST // Build a BST first..... x.put( 50 ); x.put( 30 ); x.put( 70 ); x.put( 10 ); x.put( 5 ); x.put( 7 ); x.put( 40 ); x.put( 39 ); x.put( 38 ); x.put( 45 ); x.put( 80 ); x.put( 90 ); x.put( 75 ); x.printBST(); System.out.println("Remove *************************"); System.out.println("*** remove 7 ***"); x.remove( 7 ); x.printBST(); System.out.println("*** remove 10 ***"); x.remove( 10 ); x.printBST(); System.out.println("*** remove 70 ***"); x.remove( 70 ); x.printBST(); .... } ```

Output: (the BST is printed side ways....)

 ``` [90.0] [80.0] [75.0] [70.0] [50.0] [45.0] [40.0] [39.0] [38.0] [30.0] [10.0] [7.0] [5.0] ================================ Remove ************************* *** remove 7 *** (case 1) [90.0] [80.0] [75.0] [70.0] [50.0] [45.0] [40.0] [39.0] [38.0] [30.0] [10.0] [5.0] ================================ *** remove 10 *** (case 2) [90.0] [80.0] [75.0] [70.0] [50.0] [45.0] [40.0] [39.0] [38.0] [30.0] [5.0] ================================ *** remove 70 *** (case 2) [90.0] [80.0] [75.0] [50.0] [45.0] [40.0] [39.0] [38.0] [30.0] [5.0] ================================ *** remove 30 *** (case 3 !!!) [90.0] [80.0] [75.0] [50.0] [45.0] [40.0] [39.0] [38.0] [5.0] ================================ *** remove 38 *** [90.0] [80.0] [75.0] [50.0] [45.0] [40.0] [39.0] [5.0] ================================ *** remove 50 *** [90.0] [80.0] [75.0] [45.0] [40.0] [39.0] [5.0] ================================ *** remove 75 *** [90.0] [80.0] [45.0] [40.0] [39.0] [5.0] ================================ *** remove 80 *** [90.0] [45.0] [40.0] [39.0] [5.0] ================================ *** remove 90 *** [45.0] [40.0] [39.0] [5.0] ================================ *** remove 5 *** [45.0] [40.0] [39.0] ================================ *** remove 39 *** [45.0] [40.0] ================================ *** remove 45 *** [40.0] ================================ *** remove 40 *** ================================ ```

• Example Program: (Demo above code)

How to run the program:

 Right click on link and save in a scratch directory To compile:   javac testProg2.java To run:          java testProg2