C Program to Implement Binary Search Tree

Problem Description

Write a C program to implement the Binary Search Tree operations and display its traversals.

Outline of a Binary Search Tree:

What is a Tree?

A tree is a non-linear data structure in which the data is stored non-linearly. A tree is used to represent the data in hierarchical form. It has a collection of objects that store data into its which is known as nodes.

Tree Example - Hierarchical Structure

The above image represents a tree in which four nodes are connected in a hierarchical structure. Every node contains some integer data and the address of its children.

Now, before going to understand the binary search tree let’s take a look at the binary tree and its representation.

advertisement
advertisement

What is a Binary Tree?

A binary tree is a kind of tree in which every node contains at most two children. A node contains the address of the left and right child in the linked list representation of the binary tree.

If a node does not contain either child, its field will be NULL. If there are no children for that node then it is called the Leaf node.

Binary Tree Linked List Representation

What is a Binary Search Tree?

A binary Search Tree is a special tree in which some order is followed. Every parent node has at most two children in which the left children have a lesser value while the right children have a higher value than their parent. This rule is applied to all left and right subtrees.

Binary Search Tree Example

Problem Solution

We will implement the binary search tree using the doubly linked list. A doubly linked list contains the address of the left and right children and the data of the node. The left pointer of the node points to the left children and the right pointer points to the right children.

advertisement

Here is the representation of a node using a doubly linked list.

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

Doubly Linked List representation of a BST node:

left* data right*

Program/Source Code

Here is the source code of the C program to implement the Binary Search Tree operations. The C program is successfully compiled and run on a Linux system. The program output is also shown below.

advertisement
  1. /*
  2. * C program to implement the Binary Search Tree 
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6.  
  7. // structure of a node
  8. struct node
  9. {
  10.     int data;
  11.     struct node *left;
  12.     struct node *right;
  13. };
  14.  
  15. // globally initialized root pointer
  16. struct node *root = NULL;
  17.  
  18. // function prototyping
  19. struct node *create_node(int);
  20. void insert(int);
  21. struct node *delete (struct node *, int);
  22. int search(int);
  23. void inorder(struct node *);
  24. void postorder();
  25. void preorder();
  26. struct node *smallest_node(struct node *);
  27. struct node *largest_node(struct node *);
  28. int get_data();
  29.  
  30. int main()
  31. {
  32.     int userChoice;
  33.     int userActive = 'Y';
  34.     int data;
  35.     struct node* result = NULL;
  36.  
  37.     while (userActive == 'Y' || userActive == 'y')
  38.     {
  39.         printf("\n\n------- Binary Search Tree ------\n");
  40.         printf("\n1. Insert");
  41.         printf("\n2. Delete");
  42.         printf("\n3. Search");
  43.         printf("\n4. Get Larger Node Data");
  44.         printf("\n5. Get smaller Node data");
  45.         printf("\n\n-- Traversals --");
  46.         printf("\n\n6. Inorder ");
  47.         printf("\n7. Post Order ");
  48.         printf("\n8. Pre Oder ");
  49.         printf("\n9. Exit");
  50.  
  51.         printf("\n\nEnter Your Choice: ");
  52.         scanf("%d", &userChoice);
  53.         printf("\n");
  54.  
  55.         switch(userChoice)
  56.         {
  57.             case 1:
  58.                 data = get_data();
  59.                 insert(data);
  60.                 break;
  61.  
  62.             case 2:
  63.                 data = get_data();
  64.                 root = delete(root, data);
  65.                 break;
  66.  
  67.             case 3:
  68.                 data = get_data();
  69.                 if (search(data) == 1)
  70.                 {
  71.                     printf("\nData was found!\n");
  72.                 }
  73.                 else
  74.                 {
  75.                     printf("\nData does not found!\n");
  76.                 }
  77.                 break;
  78.  
  79.             case 4:
  80.                 result = largest_node(root);
  81.                 if (result != NULL)
  82.                 {
  83.                     printf("\nLargest Data: %d\n", result->data);
  84.                 }
  85.                 break;
  86.  
  87.             case 5:
  88.                 result = smallest_node(root);
  89.                 if (result != NULL)
  90.                 {
  91.                     printf("\nSmallest Data: %d\n", result->data);
  92.                 }
  93.                 break;
  94.  
  95.             case 6:
  96.                 inorder(root);
  97.                 break;
  98.  
  99.             case 7:
  100.                 postorder(root);
  101.                 break;
  102.  
  103.             case 8:
  104.                 preorder(root);
  105.                 break;
  106.  
  107.             case 9:
  108.                 printf("\n\nProgram was terminated\n");
  109.                 break;
  110.  
  111.             default:
  112.                 printf("\n\tInvalid Choice\n");
  113.                 break;
  114.         }
  115.  
  116.         printf("\n__________\nDo you want to continue? ");
  117.         fflush(stdin);
  118.         scanf(" %c", &userActive);
  119.     }
  120.  
  121.     return 0;
  122. }
  123.  
  124. // creates a new node
  125. struct node *create_node(int data)
  126. {
  127.     struct node *new_node = (struct node *)malloc(sizeof(struct node));
  128.  
  129.     if (new_node == NULL)
  130.     {
  131.         printf("\nMemory for new node can't be allocated");
  132.         return NULL;
  133.     }
  134.  
  135.     new_node->data = data;
  136.     new_node->left = NULL;
  137.     new_node->right = NULL;
  138.  
  139.     return new_node;
  140. }
  141.  
  142. // inserts the data in the BST
  143. void insert(int data)
  144. {
  145.     struct node *new_node = create_node(data);
  146.  
  147.     if (new_node != NULL)
  148.     {
  149.         // if the root is empty then make a new node as the root node
  150.         if (root == NULL)
  151.         {
  152.             root = new_node;
  153.             printf("\n* node having data %d was inserted\n", data);
  154.             return;
  155.         }
  156.  
  157.         struct node *temp = root;
  158.         struct node *prev = NULL;
  159.  
  160.         // traverse through the BST to get the correct position for insertion
  161.         while (temp != NULL)
  162.         {
  163.             prev = temp;
  164.             if (data > temp->data)
  165.             {
  166.                 temp = temp->right;
  167.             }
  168.             else
  169.             {
  170.                 temp = temp->left;
  171.             }
  172.         }
  173.  
  174.         // found the last node where the new node should insert
  175.         if (data > prev->data)
  176.         {
  177.             prev->right = new_node;
  178.         }
  179.         else
  180.         {
  181.             prev->left = new_node;
  182.         }
  183.  
  184.         printf("\n* node having data %d was inserted\n", data);
  185.     }
  186. }
  187.  
  188. // deletes the given key node from the BST
  189. struct node *delete (struct node *root, int key)
  190. {
  191.     if (root == NULL)
  192.     {
  193.         return root;
  194.     }
  195.     if (key < root->data)
  196.     {
  197.         root->left = delete (root->left, key);
  198.     }
  199.     else if (key > root->data)
  200.     {
  201.         root->right = delete (root->right, key);
  202.     }
  203.     else
  204.     {
  205.         if (root->left == NULL)
  206.         {
  207.             struct node *temp = root->right;
  208.             free(root);
  209.             return temp;
  210.         }
  211.         else if (root->right == NULL)
  212.         {
  213.             struct node *temp = root->left;
  214.             free(root);
  215.             return temp;
  216.         }
  217.         struct node *temp = smallest_node(root->right);
  218.         root->data = temp->data;
  219.         root->right = delete (root->right, temp->data);
  220.     }
  221.     return root;
  222.  
  223. }
  224.  
  225. // search the given key node in BST
  226. int search(int key)
  227. {
  228.     struct node *temp = root;
  229.  
  230.     while (temp != NULL)
  231.     {
  232.         if (key == temp->data)
  233.         {
  234.             return 1;
  235.         }
  236.         else if (key > temp->data)
  237.         {
  238.             temp = temp->right;
  239.         }
  240.         else
  241.         {
  242.             temp = temp->left;
  243.         }
  244.     }
  245.     return 0;
  246. }
  247.  
  248. // finds the node with the smallest value in BST
  249. struct node *smallest_node(struct node *root)
  250. {
  251.     struct node *curr = root;
  252.     while (curr != NULL && curr->left != NULL)
  253.    {
  254.         curr = curr->left;
  255.     }
  256.     return curr;
  257. }
  258.  
  259. // finds the node with the largest value in BST
  260. struct node *largest_node(struct node *root)
  261. {
  262.     struct node *curr = root;
  263.     while (curr != NULL && curr->right != NULL)
  264.     {
  265.         curr = curr->right;
  266.     }
  267.     return curr;
  268. }
  269.  
  270. // inorder traversal of the BST
  271. void inorder(struct node *root)
  272. {
  273.     if (root == NULL)
  274.     {
  275.         return;
  276.     }
  277.     inorder(root->left);
  278.     printf("%d ",  root->data);
  279.     inorder(root->right);
  280. }
  281.  
  282. // preorder traversal of the BST
  283. void preorder(struct node *root)
  284. {
  285.     if (root == NULL)
  286.     {
  287.         return;
  288.     }
  289.     printf("%d ", root->data);
  290.     preorder(root->left);
  291.     preorder(root->right);
  292. }
  293.  
  294. // postorder travsersal of the BST
  295. void postorder(struct node *root)
  296. {
  297.     if (root == NULL)
  298.     {
  299.         return;
  300.     }
  301.     postorder(root->left);
  302.     postorder(root->right);
  303.     printf("%d ", root->data);
  304. }
  305.  
  306. // getting data from the user
  307. int get_data()
  308. {
  309.     int data;
  310.     printf("\nEnter Data: ");
  311.     scanf("%d", &data);
  312.     return data;
  313. }
Program Explanation

Here we have discussed the main functions of the Binary Search Tree with time and space complexities.

Insert a new Node – insert() method

To insert the new node, we have to follow the given steps:

  1. Find the node where the new node has to be inserted and store the visited node in the temp variable.
  2. Now, the new node data will be compared with temp.
  3. If the data is larger than temp data then insert the new node at the right of the temp.
  4. If the data is smaller then insert the new node at the left of the temp.

Example: Let’s insert the new node 45 in the given Binary Search Tree. We have the following steps to insert it in the right position.

Binary Search Tree - insert() Method

Time Complexity:
Worst Case: O(n)
When the binary search tree becomes a skewed tree then we need to traverse each node so the time complexity becomes O(n), where n is the number of nodes.

Best and Average Case: O(h)
In general, we need to traverse the tree up to h height, so the complex becomes O(h), where h is the height of the tree.

Space Complexity: O(1)
Space is constant in this method since we are using only temporary variables.

Run Time Testcases

In this case, we are inserting the nodes in binary search tree.

------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 1
Enter Data: 20
* node having data 20 was inserted
__________
Do you want to continue? y
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 1
Enter Data: 15
* node having data 15 was inserted
__________
Do you want to continue? y
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 1
Enter Data: 25
* node having data 25 was inserted
__________
Do you want to continue? y
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 1
Enter Data: 12
* node having data 12 was inserted
__________
Do you want to continue? y
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 1
Enter Data: 18
* node having data 18 was inserted
__________
Do you want to continue? y
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 1
Enter Data: 65
* node having data 65 was inserted
__________
Do you want to continue? n

Delete a Node – delete() Method

There are three cases to delete the node from the tree. Let’s discuss all the cases using the examples that are given below.

case 1: Deleting the leaf node
To delete the leaf node we need to traverse to the required leaf node then delete that node and update its parent.

Example: Deleting a leaf node 65.

Binary Search Tree - Deleting Leaf Node

case 2: Delete a node with one child
Remove that given node and replace it with its children.

Example: Deleting node 25, to delete node 25, we have to update it with its children node 65.

Binary Search Tree - delete() Method

case 3: Deleting a node with two children
In this case, find the inorder successor of the node to which it is deleting. Copy the content of the inorder successor node to the node. Delete the inorder successor. For this case, we can also use the inorder predecessor.

Example: Deleting node 20 from the given tree.

Binary Search Tree - delete() Method

Time Complexity:
Worst Case: O(n)
In this case the tree is a skewed tree. So we need to traverse each node.

Best and Average Case: O(h)
In general, the time complexity depends on the height(h) of the BST.

Space Complexity: O(n)
Where n is the number of nodes in the BST. In the worst case the calling stack of the node calls the total number of nodes.

Run Time Testcases

In this case, we are deleting the nodes in binary search tree.
Note: The data in the Binary Search Tree are {12 15 18 20 25 65}

------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 6
12 15 18 20 25 65 
__________
Do you want to continue? y
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 2
Enter Data: 25
__________
Do you want to continue? y
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 6
12 15 18 20 65 
__________
Do you want to continue? n

Search a Node – search() method

Searching a node in a Binary search tree takes the following steps:

  1. Compare the current node data with the key if:
    • If the key is found, then return the node.
    • If the key is lesser than the node data, move the current to the left node and again repeat step 1.
    • If the key is greater then move to the right and repeat step 1.
  2. If the node is not found then return NULL.

Example: Let’s find the node with data 15 in the given BST.

Binary Search Tree - search() Method

Time Complexity:
Worst Case: O(n)
In the worst case, we have to traverse each node. Here n is the number of nodes in the binary search tree.

Best Case and Average Case: O(h)
In this case, the complexity depends on the height h of the binary search tree.

Space Complexity: O(1)
Space is constant in this method since we are using only temporary variables.

Run Time Testcases

In this case, we are searching the nodes in binary search tree.
Note: The data in the Binary Search Tree are {12 15 18 20 25 65}

------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 3
Enter Data: 65
Data was found!
__________
Do you want to continue? y
 
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 3
Enter Data: 64
Data does not found!
__________
Do you want to continue? y
 
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 4
Largest Data: 65
_________
Do you want to continue? y
 
------- Binary Search Tree ------
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 5
Smallest Data: 12
 
__________
Do you want to continue?

Traversals of the Binary Search Tree

Inorder Traversal

In inorder traversal, we have to traverse in the following order:

  1. Traverse to the left to a given node.
  2. print the node data.
  3. Traverse to the right to a given node.

Example: Inorder traversal of the tree is given below.

Binary Search Tree Traversal

Inorder: 12, 15, 18, 20, 25, 65

Time Complexity: O(n)
Here, n is the number of nodes. We have to traverse each node in the BST.

Space Complexity: O(h)
The height of the skewed binary search tree is the number of nodes.

Run Time Testcases

In this case, we perform an in-order traversal of the binary search tree.
Note: The data in the Binary Search Tree are {12 15 18 20 25 65}

------- Binary Search Tree ------
 
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 6
12 15 18 20 25 65 
__________
Do you want to continue? n

Preorder Traversal

In preorder traversal, we have to traverse in the following order:

  1. Print the node data.
  2. Traverse to the left to a given node.
  3. Traverse to the right to a given node.

Example: Preorder traversal of the binary search tree is given below.

Binary Search Tree Traversal

Preorder: 20, 15, 12, 18, 25, 65

Time Complexity: O(n)
Here, n is the number of nodes. We have to traverse each node in the BST.

Space Complexity: O(h)
The height of the skewed binary search tree is the number of nodes.

Run Time Testcases

In this case, we perform an pre-order traversal of the binary search tree.
Note: The data in the Binary Search Tree are {12 15 18 20 25 65}

------- Binary Search Tree ------
 
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 8
20 15 12 18 25 65 
__________
Do you want to continue? n

Postorder Traversal

In preorder traversal, we have to traverse in the following order:

  1. Traverse to the left to a given node.
  2. Traverse to the right to a given node.
  3. Print the data of the node.

Example: Postorder traversal of the binary search tree is given below.

Binary Search Tree Traversal

Postorder: 12, 18, 15, 65, 25, 20

Time Complexity: O(n)
Here, n is the number of nodes. We have to traverse each node in the BST.

Space Complexity: O(h)
The height of the skewed binary search tree is the number of nodes.

Run Time Testcases

In this case, we perform an post-order traversal of the binary search tree.
Note: The data in the Binary Search Tree are {12 15 18 20 25 65}

------- Binary Search Tree ------
 
1. Insert
2. Delete
3. Search
4. Get Larger Node Data
5. Get smaller Node data
 
-- Traversals --
 
6. Inorder 
7. Post Order 
8. Pre Oder 
9. Exit
 
Enter Your Choice: 7
12 18 15 65 25 20 
__________
Do you want to continue? n

To practice programs on every topic in C, please visit “Programming Examples in C”, “Data Structures in C” and “Algorithms in C”.

If you find any mistake above, kindly email to [email protected]

advertisement
advertisement
Subscribe to our Newsletters (Subject-wise). Participate in the Sanfoundry Certification contest to get free Certificate of Merit. Join our social networks below and stay updated with latest contests, videos, internships and jobs!

Youtube | Telegram | LinkedIn | Instagram | Facebook | Twitter | Pinterest
Manish Bhojasia - Founder & CTO at Sanfoundry
Manish Bhojasia, a technology veteran with 20+ years @ Cisco & Wipro, is Founder and CTO at Sanfoundry. He lives in Bangalore, and focuses on development of Linux Kernel, SAN Technologies, Advanced C, Data Structures & Alogrithms. Stay connected with him at LinkedIn.

Subscribe to his free Masterclasses at Youtube & discussions at Telegram SanfoundryClasses.