Delete Node in a BST
Start at root node 5
Begin the deletion process at the root node with value 5. The key to delete is 3, which is less than 5, so we will search the left subtree.
if not root:
return None
if key < root.val:Recurse into left child node 3
Since key 3 is less than 5, recurse into the left child node with value 3 to continue searching for the node to delete.
root.left = deleteNode(root.left, key)Found node with value 3 to delete
At node 3, the key matches the node's value. This is the node to delete.
elif key == root.val:Check if node 3 has no left child
Check if node 3 has no left child. It does have a left child (2), so this case does not apply.
if not root.left:Check if node 3 has no right child
Check if node 3 has no right child. It does have a right child (4), so this case does not apply.
elif not root.right:Find inorder successor of node 3
Call helper function to find the inorder successor of node 3, which is the smallest node in its right subtree.
successor = findSuccessor(root)Replace node 3's value with successor's value 4
Replace the value of node 3 with the inorder successor's value 4 to maintain BST properties.
root.val = successor.valDelete successor node with value 4 in right subtree
Recursively delete the successor node with value 4 in the right subtree of the replaced node.
root.right = deleteNode(root.right, successor.val)Delete leaf node 4 (successor)
At node 4 (successor), since it has no left child, return its right child (null), effectively deleting it.
if not root.left:
return root.rightReturn updated subtree to parent node 3 (now 4)
Return null to node 3's right pointer, completing the deletion of the successor node. The subtree rooted at node 3 now has right child null.
return rootReturn updated subtree to root node 5
Return the updated left subtree (rooted at node 4) to the root node 5, completing the deletion process.
return rootFinal BST after deletion
The BST after deletion has node 4 replacing node 3, with the successor node removed. The tree maintains BST properties.
return rootclass TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def findSuccessor(node):
curr = node.right # STEP 6
while curr.left: # STEP 6 loop
curr = curr.left
return curr
def deleteNode(root, key):
if not root: # STEP 1
return None
if key < root.val: # STEP 1-2
root.left = deleteNode(root.left, key) # STEP 2
elif key > root.val: # Not used in this example
root.right = deleteNode(root.right, key)
else: # STEP 3
if not root.left: # STEP 4
return root.right
elif not root.right: # STEP 5
return root.left
else: # STEP 6
successor = findSuccessor(root) # STEP 6
root.val = successor.val # STEP 7
root.right = deleteNode(root.right, successor.val) # STEP 8
return root # STEP 10-11
Key Takeaways
Without visualization, it's hard to see how recursion narrows down the search path.
This insight is subtle in code but clear when watching the successor being found and replacing the node.
The recursive deletion of the successor node is a key step that can be overlooked without step-by-step tracing.
