× Home Insertion Deletion

Insertion in Binary Search Tree

Here is an example binary search tree, and the element we want to insert is 9.

  • Start from the root node, and check if the element you want to insert is greater than or lesser than.
  • Since 9 is greater than 8
  • move to the right of the root
  • now root is the 10
  • since this time 9 is less then 10
  • move to the left of element 10
  • since there are no elements to its left
  • insert 9 there.

This was one simple case, but things becomes more complex when you have to insert your element at some internal position and not at the leaf.

  • Before you insert a node, the first thing you would do is to create that node and allocate memory to it in heap using malloc or createNode function.
  • Initialize the node with the data given, and both the righ and the left member of the node should be marked NULL.
  • Another important thing to see here is the pointer you would follow the correct position with.
  • In above example, to be able to insert at that position, the pointer must be at node 10.
  • And then you check wheter going to the left side is good, or the right.
  • Here, you came to the left, but had it been right, we would have updated our pointer ptr further and maintained a second pointer to the previous root.

Creating the insert function

  • Create a void function insert and pass the pointer to the root node, and the data of the node you want to insert as its parameter
  • Use two struct pointers to traverse through the tree.
    • One of them would be our root which we would traverse through the nodes.
    • Another one would be prev which stores the pointer to the previous root
  • Run a while loop that is for until we reach some leaf, and couldn't traverse further.
    • So, run thant loop until the root becomes NULL
    • Inside that loop
      • make the prev = current loop. Since we would definitely move further because this root is not a NULL.
      • check, if the root itself is not equal to the node we are trying to insert. That is,
        • Write an if condition to see if there are any duplicates here
        • If there is return from the function here itself.
      • move either to the left of this root or to the right of this root.
      • Further in the loop, check if the element you want to insert is less than the current root.
        • If it is, update the root to the left element of the struct root.
        • If it isn't, update the root tot the right elment of the struct root.
        • And since we have already stored this root in the prev node, there ins't any issure updating.
      • And finally, you will have a prev node as the outcome at the end after this loop finishes.
      • Now, the only procefure left now is to link these nodes together, that it the prev node, the new node and the node next to the prev.
    • Now before you insert, make sure you create that new struct node.
                        

                            void insert(struct node *root, int key){
                                struct node *prev = NULL;
                                while(root!=NULL){
                                    prev = root;
                                    if(key==root->data){
                                        printf("Cannot insert %d, already in BST", key);
                                        return;
                                    }
                                    else if(key<root->data){
                                        root = root->left;
                                    }
                                    else{
                                        root = root->right;
                                    }
                                }
                                struct node* new = createNode(key);
                                if(key<prev->data){
                                    prev->left = new;
                                }
                                else{
                                    prev->right = new;
                                }
                             }
                             
                        
                    
                            

                                #include<stdio.h>
                                    #include<malloc.h>
                                    
                                    struct node{
                                        int data;
                                        struct node* left;
                                        struct node* right;
                                    };
                                    
                                    struct node* createNode(int data){
                                        struct node *n; // creating a node pointer
                                        n = (struct node *) malloc(sizeof(struct node)); // Allocating memory in the heap
                                        n->data = data; // Setting the data
                                        n->left = NULL; // Setting the left and right children to NULL
                                        n->right = NULL; // Setting the left and right children to NULL
                                        return n; // Finally returning the created node
                                    }
                                    void insert(struct node *root, int key){
                                       struct node *prev = NULL;
                                       while(root!=NULL){
                                           prev = root;
                                           if(key==root->data){
                                               printf("Cannot insert %d, already in BST", key);
                                               return;
                                           }
                                           else if(key<root->data){
                                               root = root->left;
                                           }
                                           else{
                                               root = root->right;
                                           }
                                       }
                                       struct node* new = createNode(key);
                                       if(key<prev->data){
                                           prev->left = new;
                                       }
                                       else{
                                           prev->right = new;
                                       }
                                    
                                    }
                                    
                                    int main(){
                                         
                                        // Constructing the root node - Using Function (Recommended)
                                        struct node *p = createNode(5);
                                        struct node *p1 = createNode(3);
                                        struct node *p2 = createNode(6);
                                        struct node *p3 = createNode(1);
                                        struct node *p4 = createNode(4);
                                        // Finally The tree looks like this:
                                        //      5
                                        //     / \
                                        //    3   6
                                        //   / \
                                        //  1   4  
                                    
                                        // Linking the root node with left and right children
                                        p->left = p1;
                                        p->right = p2;
                                        p1->left = p3;
                                        p1->right = p4;
                                    
                                        insert(p, 16);
                                        printf("%d", p->right->right->data);
                                        return 0;
                                    }                               
                            
                        

Deletion in Binary Search Tree better explained

In below example, where 4 is the element we wanted to remove and seems quite an easy job. Just search for the element and remove it.

Bul deleting in a binary search tree is no doubt a tough job like if you consider a case where the node is not a leaf node or it is a root node.

There are three cases when we have to delete a node from a binary search tree.

  • The node is leaf node.
  • The node is non-leaf node.
  • The node is root node.

Deleting a leaf node

  • It is the simplest case in deletion in binary search tree
  • Just search the element in the tree, and remove it from the tree, and make its parent node point to NULL
  • To be more specific, follow the steps below to delte a lead node along with the illustration of how we delete a lead node in the above tree.
  • Search the node
  • Delete the node.
  • Point the parent node to NULL

Deleting a non-leaf node

  • Here we can't just make its parent point to NULL.
  • We have to deal with the children of this node.
  • Let's try to delete 6
  • First search the element 6
  • Now the dilemma is, which node will replace the position of node 6.
  • When you delete a node that is not a leaf node, you replace its position with its InOrder predecessor or InOrder successor.
  • So, what does that mean?
    • If you write the InOrder traversal of the above tree.
    • the nodes coming immediately before or after node 6, will be the one replacing it.
    • InOrder traversal = 1→ 3→ 4 →6 →7→ 8→ 10→ 13→ 14
  • So, the InOrdr predecessor and the InOrder successor of node 6 are 4 and 7 respectively.
  • Hence we can substitute node 6 with any of these nodes, and the tree will still be valid binary search tree.
  • So, both are still binary search tree.
  • In the first case, we replaced node 6 with 4, and the right subtree of node 4 is 7, which is still bigger than it.
  • And in the second case, we replaced node 6 with node 7.
  • And the left subtree of node 7 is 4 which is still smaller than the node. Hence, both cases are win-win case.

Deleting the root node.

  • If you carefully observe, the root node is still another non-leaf node.
  • So, the basics to delete the root node remains the same as deleting non-leaf node.
  • But since the root node holds a big size of subtrees along with, we have put this as a separate case here.
  • So, the first thing you do is write the InOrder traversal of the whole tree, and then replace the position of the root node with its InOrder predecessor or InOrder successor
  • The traversal order = 1→ 3→ 4 →6 →7→ 8→ 10→ 13→ 14
  • So, the InOrder predecessor and the InOrder successor of the root node 8 are 7 and 10 respectively
  • Hence you can substitute node 8 with any of these nodes
  • But there is a catch here. So, if you substitute the root node here, with its InOrder predecessor 7, the tree will still be a binary search tree,
  • But, when you substitute the root node here, with its InOrder successor 10, there still becomes an empty position where node 10 used to be.
  • So, we still placed the InOrder successor of 10, which was 13 on the position where 10 used to be. And then there are no empty nodes in between. This finalizes our deletion.
  • So, there are few steps:
    1. search the node to be deleted
    2. search for the InOrder predecessor and successor of the node
    3. keep doing that until the tree has no empty nodes
    4. and this case is not limited to the root nodes, rather any nodes falling in between a tree.
    5. well, there could be a case where the node was not found in the tree, so, for that, we would reverst the statement that the node could note be found.
                        

                            #include <stdio.h>
                                #include <stdlib.h>
                                
                                struct node
                                {
                                    int data;
                                    struct node *left;
                                    struct node *right;
                                };
                                struct node *createNode(int data)
                                {
                                    struct node *n;
                                    n = (struct node *)malloc(sizeof(struct node)); 
                                    n->data = data;                                 
                                    n->left = NULL;                                 
                                    n->right = NULL;                                
                                    return n;                                       
                                }
                                void inOrder(struct node *root)
                                {
                                    if (root != NULL)
                                    {
                                        inOrder(root->left);
                                        printf("%d ", root->data);
                                        inOrder(root->right);
                                    }
                                }
                                
                                struct node *inOrderPredecessor(struct node *root)
                                {
                                    root = root->left;
                                    while (root->right != NULL)
                                    {
                                        root = root->right;
                                    }
                                    return root;
                                }
                                struct node *deleteNode(struct node *root, int value)
                                {
                                    struct node *iPre;
                                    if (root == NULL)
                                    {
                                        return NULL;
                                    }
                                    if (root->left == NULL && root->right == NULL)
                                    {
                                        free(root);
                                        return NULL;
                                    }
                                    // search for the node to be deleted
                                    if (value < root->data)
                                    {
                                        root->left = deleteNode(root->left, value);
                                    }
                                    else if (value > root->data)
                                    {
                                        root->right = deleteNode(root->right, value);
                                    }
                                    // Deletion strategy when the node is found
                                    else
                                    {
                                        iPre = inOrderPredecessor(root);
                                        root->data = iPre->data;
                                        root->left = deleteNode(root->left, iPre->data);
                                    }
                                    return root;
                                }
                                
                                int main()
                                {
                                    // constructing the root node - Using Function (Recommended)
                                    struct node *p = createNode(5);
                                    struct node *p1 = createNode(3);
                                    struct node *p2 = createNode(6);
                                    struct node *p3 = createNode(1);
                                    struct node *p4 = createNode(4);
                                
                                    //          5
                                    //        /   \ 
                                    //       3     6
                                    //     /   \   
                                    //    1     4
                                
                                    // Linkng the rootnode with left and right childre
                                    p->left = p1;
                                    p->right = p2;
                                    p1->left = p3;
                                    p1->right = p4;
                                
                                    inOrder(p);
                                    printf("\n");
                                    deleteNode(p, 5);
                                    inOrder(p);
                                
                                    return 0;
                                }