C Programming Data Structures Insertion Deletion In Bst Complete Guide

 Last Update:2025-06-23T00:00:00     .NET School AI Teacher - SELECT ANY TEXT TO EXPLANATION.    10 mins read      Difficulty-Level: beginner

Understanding the Core Concepts of C Programming data structures Insertion, Deletion in BST

Binary Search Tree (BST)

A Binary Search Tree is a node-based binary tree data structure that has the following properties:

  1. Each node has at most two children, referred to as the left child and the right child.
  2. For each node, all elements in its left subtree are less than the node’s element, and all elements in its right subtree are greater than the node’s element.

These properties facilitate efficient searching, insertion, and deletion operations.

Insertion in BST

Inserting an element in a BST involves creating a new node and finding the correct position for it based on the BST properties.

Steps for Insertion:

  1. Start from the root node of the BST.
  2. Compare the key of the new node with the root node’s key.
    • If the new key is lesser, traverse to the left child.
    • If the new key is greater, traverse to the right child.
  3. Repeat the comparison process until you find an empty spot (i.e., NULL child):
    • If the current node's left child is NULL and the new key should be there, insert the new node as the left child.
    • If the current node's right child is NULL and the new key should be there, insert the new node as the right child.
  4. After finding the appropriate spot, create the new node and adjust the parent pointers (left or right) accordingly.

Sample Code for Insertion:

struct Node {
    int key;
    struct Node *left, *right;
};

// Utility function to create a new node
struct Node* newNode(int item) {
    struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->key = item;
    temp->left = temp->right = NULL;
    return temp;
}

// Function to insert a new node with given key in BST
struct Node* insert(struct Node* node, int key) {
    // If the tree is empty, return a new node
    if (node == NULL) return newNode(key);

    // Otherwise, recur down the tree
    if (key < node->key)
        node->left = insert(node->left, key);
    else if (key > node->key)
        node->right = insert(node->right, key);
    
    // Return the unchanged node pointer
    return node;
}

Deletion in BST

Deleting an element from a BST requires different strategies based on the characteristics of the node to be deleted:

  • Node with no children (leaf node): Simply remove the node.
  • Node with one child: Remove the node and link the parent to the child.
  • Node with two children: Find inorder successor (the node with the smallest key in the right subtree), copy its content to the node, and then recursively delete the inorder successor.

Types of Deletion:

  1. Leaf Node Deletion: The node being deleted has no children. In this case, simply free the memory allocated for it and point the parent’s left or right pointer to NULL.

  2. Node with One Child: Locate the appropriate child and point the parent’s pointer directly to that child. Then, free the memory allocated to the node.

  3. Node with Two Children: Replace the key of the node to be deleted with the key of its inorder successor (leftmost node in the right subtree). Delete the inorder successor, which might fall in one of the first two categories (node with no children or one child).

Sample Code for Deletion:

// Given a non-empty binary search tree, return the node with minimum key value found in that tree. Note that the entire tree does not need to be searched.
struct Node* minValueNode(struct Node* node) {
    struct Node* current = node;

    // Loop down to find the leftmost leaf
    while (current && current->left != NULL)
        current = current->left;

    return current;
}

// Function to delete a node with given key from BST
struct Node* deleteNode(struct Node* root, int key) {
    // Base case
    if (root == NULL) return root;

    // If the key to be deleted is smaller than the root's key, then it lies in left subtree
    if (key < root->key)
        root->left = deleteNode(root->left, key);
    // If the key to be deleted is greater than the root's key, then it lies in right subtree
    else if (key > root->key)
        root->right = deleteNode(root->right, key);
    // If key is same as root's key, then This is the node to be deleted
    else {
        // 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)
        struct Node* temp = minValueNode(root->right);

        // Copy the inorder successor's content to this node
        root->key = temp->key;

        // Delete the inorder successor
        root->right = deleteNode(root->right, temp->key);
    }
    return root;
}

Important Information:

  • Time Complexity:

    • Average time complexity for insertion and deletion is (O(\log n)).
    • However, in the worst case (unbalanced tree, such as linked list), the time complexity can degrade to (O(n)).
  • Balancing: For optimal performance, the BST should be balanced. Various techniques exist, such as AVL trees, Red-Black trees, or self-balancing binary search trees, that maintain balance after insertions and deletions.

  • Memory Management: Care must be taken in managing memory, especially during deletion. Properly freeing nodes ensures that there are no memory leaks.

  • Recursive vs Iterative: Both recursive and iterative methods can be used for insertion and deletion. The recursive method is more straightforward but might consume more stack space for very deep trees.

  • Inorder Traversal and Successors:

    • The inorder successor is used when deleting nodes with two children because it maintains the order property of the BST.
    • The inorder predecessor (largest in the left subtree) can also be used depending on specific implementation requirements.

Online Code run

🔔 Note: Select your programming language to check or run code at

💻 Run Code Compiler

Step-by-Step Guide: How to Implement C Programming data structures Insertion, Deletion in BST

Binary Search Tree (BST) Basics

A Binary Search Tree (BST) is a node-based binary tree data structure which has the following properties:

  1. The left subtree of a node contains only nodes with keys lesser than the node’s key.
  2. The right subtree of a node contains only nodes with keys greater than the node’s key.
  3. The left and right subtree each must also be a binary search tree.

Node Structure:

struct Node {
    int data;
    struct Node* left;
    struct Node* right;
};

Insertion in BST

To insert a new node into a BST, we need to maintain the properties of BST. Here is how it can be done:

Step-by-Step Instructions:

  1. Define the Node Structure: As shown above.
  2. Create a Function to Allocate Memory for a New Node:
    • This function will create a new node with the provided data and return a pointer to the newly created node.
    • Initialize its left and right pointers to NULL.
  3. Create a Function to Insert Nodes into the BST:
    • It should take the root of the tree and the data of the new node as input arguments.
    • If the root (key) is NULL, this case denotes that we have reached a leaf node. Create a new node here and return its address.
    • Otherwise, compare the new element with the current root element.
    • If the new element is less than the current root element, recursively insert the new element in the left sub-tree.
    • If the new element is more than the current root element, recursively insert the new element in right sub-tree.

Complete Example Code:

#include <stdio.h>
#include <stdlib.h>

// Define the Node structure
struct Node {
    int data;
    struct Node* left;
    struct Node* right;
};

// Function to create a new node
struct Node* newNode(int data) {
    struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->data = data;
    temp->left = NULL;
    temp->right = NULL;
    return temp;
}

// Function to insert nodes into the BST
struct Node* insert(struct Node* root, int data) {
    if (root == NULL)
        return newNode(data);

    // Recursively insert in the right or left subtree
    if (data < root->data)
        root->left = insert(root->left, data);
    else if (data > root->data)
        root->right = insert(root->right, data);

    return root;
}

// Helper function to print the BST elements (inorder traversal)
void inorderTraverse(struct Node* root) {
    if (root != NULL) {
        inorderTraverse(root->left);
        printf("%d ", root->data);
        inorderTraverse(root->right);
    }
}

// Main function
int main() {
    struct Node* root = NULL;
    root = insert(root, 45);
    insert(root, 35);
    insert(root, 70);
    insert(root, 50);
    insert(root, 90);
    insert(root, 10);
    insert(root, 60);

    printf("Inorder Traversal of the BST: ");
    inorderTraverse(root);
    printf("\n");

    return 0;
}

Deletion in BST

Deletion in a Binary Search Tree can be a bit complex compared to insertion. When deleting a node, three possibilities arise:

  1. The node to be deleted is a leaf node.
  2. The node to be deleted has only one child.
  3. The node to be deleted has two children (both sub-trees).

Step-by-Step Instructions:

  1. Define a Min Value Node Finder Function: To find the minimum value node in a tree.
    • This minimum value node is useful when the deleted node has two children.
  2. Create a Function to Delete Nodes from the BST:
    • It should take the root of the tree and the data to be deleted as input arguments.
    • First, search for the node you want to delete.
    • Now, there are four cases:
      • If the node to be deleted does not exist, just return the original root.
      • If the node to be deleted is smaller than the root, then recurse on the left subtree.
      • If the node to be deleted is greater than the root, then recurse on the right subtree.
      • If the node to be deleted is the root itself:
        • Case 1: The node has no children - it is a leaf node. Simply set the root to NULL.
        • Case 2: One child - Copy the child to the root and delete the child.
        • Case 3: Two children - Find the smallest element in the right subtree (this is an inorder successor), copy its value in the root node, and then delete the inorder successor.

Complete Example Code:

#include <stdio.h>
#include <stdlib.h>

// Define the Node structure
struct Node {
    int data;
    struct Node* left;
    struct Node* right;
};

// Function to create a new node
struct Node* newNode(int data) {
    struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->data = data;
    temp->left = NULL;
    temp->right = NULL;
    return temp;
}

// Function to insert nodes into the BST
struct Node* insert(struct Node* root, int data) {
    if (root == NULL)
        return newNode(data);
    if (data < root->data)
        root->left = insert(root->left, data);
    else if (data > root->data)
        root->right = insert(root->right, data);
    return root;
}

// Helper function to print the BST elements (inorder traversal)
void inorderTraverse(struct Node* root) {
    if (root != NULL) {
        inorderTraverse(root->left);
        printf("%d ", root->data);
        inorderTraverse(root->right);
    }
}

// Function to find the minimum value node in a BST
struct Node* findMinNode(struct Node* node) {
    struct Node* current = node;

    // Traverse the left subtree to find the leftmost leaf
    while (current && current->left != NULL)
        current = current->left;

    return current;
}

// Function to delete a node from the BST
struct Node* deleteNode(struct Node* root, int data) {
    // Base case: Empty tree or node not found
    if (root == NULL)
        return root;

    // Recursively search for the node to delete
    if (data < root->data)
        root->left = deleteNode(root->left, data);
    else if (data > root->data)
        root->right = deleteNode(root->right, data);
    // Node to be deleted found
    else {
        // **CASE 1:** Node with only one child (or no children)
        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;
        }

        // **CASE 2:** Node with two children
        // Get the inorder successor
        struct Node* temp = findMinNode(root->right);
        root->data = temp->data;  // Copy inorder successor's content to this node
        root->right = deleteNode(root->right, temp->data);  // Delete inorder successor
    }
    return root;
}

// Main function
int main() {
    struct Node* root = NULL;
    root = insert(root, 45);
    insert(root, 35);
    insert(root, 70);
    insert(root, 50);
    insert(root, 90);
    insert(root, 10);
    insert(root, 60);

    printf("Inorder Traversal of the BST before deletion: ");
    inorderTraverse(root);
    printf("\n");

    root = deleteNode(root, 50);
    printf("Inorder Traversal of the BST after deleting 50: ");
    inorderTraverse(root);
    printf("\n");

    root = deleteNode(root, 90);
    printf("Inorder Traversal of the BST after deleting 90: ");
    inorderTraverse(root);
    printf("\n");

    root = deleteNode(root, 60);
    printf("Inorder Traversal of the BST after deleting 60: ");
    inorderTraverse(root);
    printf("\n");

    return 0;
}

Running the Code

Compile and run the insertion-deletion BST example program. You will get the following output:

Inorder Traversal of the BST before deletion: 10 35 45 50 60 70 90 
Inorder Traversal of the BST after deleting 50: 10 35 45 60 70 90 
Inorder Traversal of the BST after deleting 90: 10 35 45 60 70 
Inorder Traversal of the BST after deleting 60: 10 35 45 70 

This output confirms that:

  • The nodes are correctly inserted into the BST maintaining the BST property.
  • The specified nodes are correctly deleted and the resulting trees still maintain the BST properties.

Top 10 Interview Questions & Answers on C Programming data structures Insertion, Deletion in BST

1. What is a Binary Search Tree (BST)?

Answer: A Binary Search Tree (BST) is a node-based binary tree data structure which has the following properties:

  • The left subtree of a node contains only nodes with keys less than the node’s key.
  • The right subtree of a node contains only nodes with keys greater than the node’s key.
  • The left and right subtree each must also be a binary search tree.

2. How do you insert a node into a Binary Search Tree?

Answer: To insert a node into a BST, start from the root node and recursively find the correct position based on the comparison between new data and existing nodes. If the new data is less than the current node's data, move to the left child; if it's greater, move to the right child. Continue this process until you reach a leaf node where the new node can be attached.

struct Node* insert(struct Node* root, int data) {
    if (root == NULL)
        return newNode(data); // Create new node in base case
    
    if (data < root->data)
        root->left  = insert(root->left, data);
    else if (data > root->data)
        root->right = insert(root->right, data);
    
    return root;
}

3. What are the different scenarios for deleting a node from a Binary Search Tree?

Answer: There are three scenarios:

  • No Child (Leaf Node): Simply remove the node.
  • One Child: Remove the node and link its parent to its child.
  • Two Children:
    • Find the Inorder Successor (smallest in the right subtree) or Inorder Predecessor (largest in the left subtree).
    • Replace the node's value with the successor or predecessor's value.
    • Delete the successor or predecessor node (which will now have at least one less child).

4. Write a code snippet to delete a node from a BST.

Answer:

struct Node* minValueNode(struct Node* node) {
    struct Node* current = node;
    while (current && current->left != NULL)
        current = current->left;
    return current;
}

struct Node* deleteNode(struct Node* root, int data) {
    if (root == NULL)
        return root;

    if (data < root->data)
        root->left = deleteNode(root->left, data);
    else if (data > root->data)
        root->right = deleteNode(root->right, data);
    else { // 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 smallest in the right subtree
        struct Node* temp = minValueNode(root->right);

        // Copy the inorder successor's content to this node
        root->data = temp->data;

        // Delete the inorder successor
        root->right = deleteNode(root->right, temp->data);
    }
    return root;
}

5. Explain the time complexity of insertion and deletion in a BST.

Answer: The time complexity for both insertion and deletion operations is (O(h)), where (h) is the height of the tree. In the average case for balanced trees, this simplifies to (O(\log n)). However, in the worst case (unbalanced tree, like a linked list), the time complexity becomes (O(n)).

6. Why is it important to balance a BST?

Answer: Balancing a BST ensures that operations such as insertion, deletion, and lookup run in (O(\log n)) time, making the data structure efficient. An unbalanced BST can degrade to the performance of a linked list ((O(n))) in the worst-case scenario.

7. Can a BST contain duplicate elements?

Answer: Traditional BSTs do not allow duplicate elements, but modifications can permit duplicates typically by having each node keep track of the count of occurrences or by always attaching duplicates to the right subtree or left subtree.

8. How do you handle duplicate elements in a BST?

Answer: One method to handle duplicates is to add an additional field count in the Node structure. When inserting a duplicate, instead of creating a new node, increment the count of the existing node. Alternatively, duplicates can be inserted consistently in the left or in the right subtree.

9. What is the difference between a simple BST and a Self-Balancing BST like AVL or Red-Black Tree?

Answer: A simple BST does not guarantee that the tree will remain balanced as elements are added or removed, leading to inefficient operations in the worst case. Self-balancing BSTs automatically adjust their height after insertion or deletion operations to maintain balance, ensuring that operations remain efficient.

10. How do you perform an iterative insertion in a Binary Search Tree?

Answer: Iterative insertion involves traversing the tree iteratively (using loops) rather than through recursive function calls to find the correct position for the new node.

You May Like This Related .NET Topic

Login to post a comment.