Optimized Recursive Delete in BST
Last Updated :
29 Jul, 2024
We have discussed recursive implementation of BST delete. In this post, we are going to discuss an optimization over the previous implementation. The optimization is mainly for the case when both left and right children are not empty for a node to be deleted. In the earlier implementation, we followed the following steps for this case
1) Find the inorder successor
2) Replace the node's key with the successor's key
3 Delete the successor using a recursive call to the delete method in the right subtree
With above steps, we do two traversals of the right subtree (in step 1 and 3). We can achieve the task with one traversal only and avoid a recursive call. While finding the inorder successor, we keep track of the parent of the successor also. With the help of parent pointer . reference, we can delete the node without making a recursive call. Below is the implementation of the idea.
C++
#include <bits/stdc++.h>
using namespace std;
struct Node {
int key;
Node* left;
Node* right;
Node(int k)
{
key = k;
left = right = NULL;
}
};
/* Given a binary search tree and a key, this
function deletes the key and returns the
new root */
Node* delNode(Node* root, int k)
{
// Base case
if (root == NULL)
return root;
// If the key to be deleted is smaller than
// the root's key, then it lies in the left
// subtree
if (k < root->key) {
root->left = delNode(root->left, k);
return root;
}
// If the key to be deleted is greater
// than the root's key, then it lies in
// the right subtree
else if (k > root->key) {
root->right = delNode(root->right, k);
return root;
}
// If key is same as root's key, then this
// is the node to be deleted
// Node with only one child or no child
if (root->left == NULL) {
Node* temp = root->right;
delete root;
return temp;
}
else if (root->right == NULL) {
Node* temp = root->left;
delete root;
return temp;
}
// Node with two children: Get the inorder
// successor (smallest in the right subtree).
// Also find parent of the successor
Node* succParent = root;
Node* succ = root->right;
while (succ->left != NULL) {
succParent = succ;
succ = succ->left;
}
// Copy the inorder successor's content
// to this node
root->key = succ->key;
// Delete the inorder successor
if (succParent->left == succ)
succParent->left = succ->right;
else
succParent->right = succ->right;
delete succ;
return root;
}
// Utility function to do inorder
// traversal
void inorder(Node* root)
{
if (root != NULL) {
inorder(root->left);
cout << root->key << " ";
inorder(root->right);
}
}
// Driver code
int main()
{
Node* root = new Node(10);
root->left = new Node(5);
root->right = new Node(15);
root->right->left = new Node(12);
root->right->right = new Node(18);
int x = 15;
root = delNode(root, x);
inorder(root);
return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
struct Node {
int key;
struct Node* left;
struct Node* right;
};
/* Given a binary search tree and a key, this
function deletes the key and returns the
new root */
struct Node* delNode(struct Node* root, int k) {
// Base case
if (root == NULL) {
return root;
}
// If the key to be deleted is smaller than
// the root's key, then it lies in the left
// subtree
if (k < root->key) {
root->left = delNode(root->left, k);
return root;
}
// If the key to be deleted is greater
// than the root's key, then it lies in
// the right subtree
else if (k > root->key) {
root->right = delNode(root->right, k);
return root;
}
// If key is same as root's key, then this
// is the node to be deleted
// Node with only one child or no child
if (root->left == NULL) {
struct Node* temp = root->right;
free(root);
return temp;
} else if (root->right == NULL) {
struct Node* temp = root->left;
free(root);
return temp;
}
// Node with two children: Get the inorder
// successor (smallest in the right subtree).
// Also find parent of the successor
struct Node* succParent = root;
struct Node* succ = root->right;
while (succ->left != NULL) {
succParent = succ;
succ = succ->left;
}
// Copy the inorder successor's content
// to this node
root->key = succ->key;
// Delete the inorder successor
if (succParent->left == succ) {
succParent->left = succ->right;
} else {
succParent->right = succ->right;
}
free(succ);
return root;
}
// Utility function to do inorder traversal
void inorder(struct Node* root) {
if (root != NULL) {
inorder(root->left);
printf("%d ", root->key);
inorder(root->right);
}
}
struct Node* createNode(int key) {
struct Node* newNode =
(struct Node*)malloc(sizeof(struct Node));
newNode->key = key;
newNode->left = newNode->right = NULL;
return newNode;
}
// Driver code
int main() {
struct Node* root = createNode(10);
root->left = createNode(5);
root->right = createNode(15);
root->right->left = createNode(12);
root->right->right = createNode(18);
int x = 15;
root = delNode(root, x);
inorder(root);
printf("\n");
return 0;
}
Java
class Node {
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
class GfG {
/* Given a binary search tree and a key, this
function deletes the key and returns the
new root */
static Node delNode(Node root, int k) {
// Base case
if (root == null) {
return root;
}
// If the key to be deleted is smaller than
// the root's key, then it lies in the left
// subtree
if (k < root.key) {
root.left = delNode(root.left, k);
return root;
}
// If the key to be deleted is greater
// than the root's key, then it lies in
// the right subtree
else if (k > root.key) {
root.right = delNode(root.right, k);
return root;
}
// If key is same as root's key, then this
// is the node to be deleted
// Node with only one child or no child
if (root.left == null) {
return root.right;
} else if (root.right == null) {
return root.left;
}
// Node with two children: Get the inorder
// successor (smallest in the right subtree).
// Also find parent of the successor
Node succParent = root;
Node succ = root.right;
while (succ.left != null) {
succParent = succ;
succ = succ.left;
}
// Copy the inorder successor's content
// to this node
root.key = succ.key;
// Delete the inorder successor
if (succParent.left == succ) {
succParent.left = succ.right;
} else {
succParent.right = succ.right;
}
return root;
}
// Utility function to do inorder traversal
static void inorder(Node root) {
if (root != null) {
inorder(root.left);
System.out.print(root.key + " ");
inorder(root.right);
}
}
// Driver code
public static void main(String[] args) {
Node root = new Node(10);
root.left = new Node(5);
root.right = new Node(15);
root.right.left = new Node(12);
root.right.right = new Node(18);
int x = 15;
root = delNode(root, x);
inorder(root);
}
}
Python
class Node:
def __init__(self, key):
self.key = key
self.left = None
self.right = None
def del_node(root, k):
# Given a binary search tree and a key, this
# function deletes the key and returns the
# new root
if root is None:
return root
# If the key to be deleted is smaller than
# the root's key, then it lies in the left
# subtree
if k < root.key:
root.left = del_node(root.left, k)
return root
# If the key to be deleted is greater than
# the root's key, then it lies in the right
# subtree
elif k > root.key:
root.right = del_node(root.right, k)
return root
# If key is same as root's key, then this
# is the node to be deleted
# Node with only one child or no child
if root.left is None:
return root.right
elif root.right is None:
return root.left
# Node with two children: Get the inorder
# successor (smallest in the right subtree)
succ_parent = root
succ = root.right
while succ.left is not None:
succ_parent = succ
succ = succ.left
# Copy the inorder successor's content to
# this node
root.key = succ.key
# Delete the inorder successor
if succ_parent.left == succ:
succ_parent.left = succ.right
else:
succ_parent.right = succ.right
return root
# Utility function to do inorder traversal
def inorder(root):
if root is not None:
inorder(root.left)
print(root.key, end=" ")
inorder(root.right)
# Driver code
if __name__ == "__main__":
root = Node(10)
root.left = Node(5)
root.right = Node(15)
root.right.left = Node(12)
root.right.right = Node(18)
x = 15
root = del_node(root, x)
inorder(root)
print()
C#
using System;
class Node {
public int Key;
public Node Left, Right;
public Node(int key) {
Key = key;
Left = null;
Right = null;
}
}
class GfG {
// Given a binary search tree and a key, this
// function deletes the key and returns the
// new root
public static Node DelNode(Node root, int k) {
// Base case
if (root == null) {
return root;
}
// If the key to be deleted is smaller than
// the root's key, then it lies in the left
// subtree
if (k < root.Key) {
root.Left = DelNode(root.Left, k);
return root;
}
// If the key to be deleted is greater than
// the root's key, then it lies in the right
// subtree
else if (k > root.Key) {
root.Right = DelNode(root.Right, k);
return root;
}
// If key is same as root's key, then this
// is the node to be deleted
// Node with only one child or no child
if (root.Left == null) {
return root.Right;
} else if (root.Right == null) {
return root.Left;
}
// Node with two children: Get the inorder
// successor (smallest in the right subtree)
Node succParent = root;
Node succ = root.Right;
while (succ.Left != null) {
succParent = succ;
succ = succ.Left;
}
// Copy the inorder successor's content to
// this node
root.Key = succ.Key;
// Delete the inorder successor
if (succParent.Left == succ) {
succParent.Left = succ.Right;
} else {
succParent.Right = succ.Right;
}
return root;
}
// Utility function to do inorder traversal
public static void Inorder(Node root) {
if (root != null) {
Inorder(root.Left);
Console.Write(root.Key + " ");
Inorder(root.Right);
}
}
// Main method
public static void Main() {
Node root = new Node(10);
root.Left = new Node(5);
root.Right = new Node(15);
root.Right.Left = new Node(12);
root.Right.Right = new Node(18);
int x = 15;
root = DelNode(root, x);
Inorder(root);
Console.WriteLine();
}
}
JavaScript
class Node {
constructor(key) {
this.key = key;
this.left = null;
this.right = null;
}
}
function delNode(root, k) {
// Given a binary search tree and a key, this
// function deletes the key and returns the
// new root
if (root === null) {
return root;
}
// If the key to be deleted is smaller than
// the root's key, then it lies in the left
// subtree
if (k < root.key) {
root.left = delNode(root.left, k);
return root;
}
// If the key to be deleted is greater than
// the root's key, then it lies in the right
// subtree
else if (k > root.key) {
root.right = delNode(root.right, k);
return root;
}
// If key is same as root's key, then this
// is the node to be deleted
// Node with only one child or no child
if (root.left === null) {
return root.right;
} else if (root.right === null) {
return root.left;
}
// Node with two children: Get the inorder
// successor (smallest in the right subtree)
let succParent = root;
let succ = root.right;
while (succ.left !== null) {
succParent = succ;
succ = succ.left;
}
// Copy the inorder successor's content to
// this node
root.key = succ.key;
// Delete the inorder successor
if (succParent.left === succ) {
succParent.left = succ.right;
} else {
succParent.right = succ.right;
}
return root;
}
// Utility function to do inorder traversal
function inorder(root) {
if (root !== null) {
inorder(root.left);
process.stdout.write(root.key + " ");
inorder(root.right);
}
}
// Example usage
let root = new Node(10);
root.left = new Node(5);
root.right = new Node(15);
root.right.left = new Node(12);
root.right.right = new Node(18);
const x = 15;
root = delNode(root, x);
inorder(root);
console.log();
Time Complexity: O(h), where h is the height of the BST.
Auxiliary Space: O(h).