Open In App

Optimized Recursive Delete in BST

Last Updated : 29 Jul, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

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();

Output
5 10 12 18 


Time Complexity: O(h), where h is the height of the BST. 
Auxiliary Space: O(h).



Next Article

Similar Reads