C Program to Implement Binary Tree

Problem Description

Write a C program to implement the Binary 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.

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.

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

Sanfoundry Certification Contest of the Month is Live. 100+ Subjects. Participate Now!

Problem Solution

We will implement the binary 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.

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 Binary Tree node:

left* data right*
advertisement

Program/Source Code

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

  1. /*
  2.  * C Program to Implement the Binary Tree
  3.  */
  4.  
  5. #include<stdio.h>
  6. #include<stdlib.h>
  7. #define MAX_SIZE 25
  8. #define max(a, b) a>b ? a : b
  9.  
  10. struct TreeNode
  11. {
  12.     int val;
  13.     struct TreeNode* left;
  14.     struct TreeNode* right;
  15. };
  16.  
  17. // global root declaration
  18. struct TreeNode* root = NULL;
  19.  
  20. // function prototyping
  21. void insert(int);
  22. void delete(int);
  23. int search(int);
  24. int height(struct TreeNode*);
  25. void inorder(struct TreeNode*);
  26. void preorder(struct TreeNode*);
  27. void postorder(struct TreeNode*);
  28. void levelorder();
  29.  
  30. int main()
  31. {
  32.     int user_choice, node_data;
  33.     char user_active = 'Y';
  34.  
  35.     while(user_active == 'Y' || user_active == 'y')
  36.     {
  37.         printf("\n\n--- Binary Tree --\n\n");
  38.         printf("\n1. Insert ");
  39.         printf("\n2. Delete");
  40.         printf("\n3. Search");
  41.         printf("\n4. Height");
  42.         printf("\n5. Inorder Traversal");
  43.         printf("\n6. Preorder Traversal");
  44.         printf("\n7. Postorder Traversal");
  45.         printf("\n8. Level order Traversal");
  46.         printf("\n9. Exit");
  47.         printf("\n\nEnter Your Choice: ");
  48.         scanf("%d", &user_choice);
  49.  
  50.         printf("\n");
  51.         switch(user_choice)
  52.         {
  53.             case 1:
  54.                 printf("Enter data for new node: ");
  55.                 scanf("%d", &node_data);
  56.                 insert(node_data);
  57.                 break;
  58.  
  59.             case 2:
  60.                 printf("Enter node data: ");
  61.                 scanf("%d", &node_data);
  62.                 delete(node_data);
  63.                 break;
  64.  
  65.             case 3: 
  66.                 printf("Enter node data: ");
  67.                 scanf("%d", &node_data);
  68.                 int has_found = search(node_data);
  69.  
  70.                 if(has_found == -1) {
  71.                     printf("\nNode was not found!");
  72.                 } else {
  73.                     printf("\nNode was found");
  74.                 }
  75.                 break;
  76.  
  77.             case 4: 
  78.                 printf("height of the tree is: %d", height(root));
  79.                 break;
  80.  
  81.             case 5: 
  82.                 printf("Inorder Traversal\n\n");
  83.                 inorder(root);
  84.                 break;
  85.  
  86.             case 6: 
  87.                 printf("Preorder Traversal\n\n");
  88.                 preorder(root);
  89.                 break;
  90.  
  91.             case 7: 
  92.                 printf("Postorder Traversal\n\n");
  93.                 postorder(root);
  94.                 break;
  95.  
  96.             case 8:
  97.                 printf("Level order Traversal\n\n");
  98.                 levelorder();
  99.                 break;
  100.  
  101.             case 9:
  102.                 printf("Program is terminating...\n\n");
  103.                 exit(0);
  104.  
  105.             default:
  106.                 printf("Invalid choice");
  107.         }
  108.  
  109.         fflush(stdin);
  110.         printf("\n\n\nDo you want to continue? (Y/N) ");
  111.         scanf("%c", &user_active);
  112.     }
  113.     return 0;
  114. }
  115.  
  116. struct TreeNode* create(int data)
  117. {
  118.     struct TreeNode* new_node = (struct TreeNode*) malloc (sizeof(struct TreeNode));    
  119.     if(new_node == NULL)
  120.     {
  121.         printf("\nMemory can't be allocated for new node\n");
  122.         return NULL;
  123.     }
  124.  
  125.     new_node->left = NULL;
  126.     new_node->right = NULL;
  127.     new_node->val = data;
  128.  
  129.     return new_node;
  130. }
  131.  
  132. // inserts a new node in the tree
  133. void insert(int data)
  134. {
  135.     if(root == NULL)
  136.     {
  137.         struct TreeNode* new_node = create(data);
  138.         if(new_node)
  139.         {
  140.             root = new_node;
  141.             printf("\n * Node with data %d was inserted", data);
  142.         }
  143.         return;
  144.     }
  145.  
  146.     struct TreeNode* queue[MAX_SIZE];
  147.     struct TreeNode* new_node = NULL;
  148.     int front = -1;
  149.     int rear = -1;
  150.     queue[front+1] = root;
  151.     front = rear = 0;
  152.  
  153.     while(front <= rear)
  154.     {
  155.         struct TreeNode* temp = queue[front];
  156.         front++;
  157.  
  158.         if(temp->left != NULL)
  159.         {
  160.             queue[++rear] = temp->left;
  161.         }
  162.         else
  163.         {
  164.             new_node = create(data);
  165.             if(new_node)
  166.             {
  167.                 temp->left = new_node;
  168.                 printf("\n* Node with data %d was inserted", data);
  169.             }
  170.             return;
  171.         }
  172.  
  173.         if(temp->right != NULL)
  174.         {
  175.             queue[++rear] = temp->right;
  176.         }
  177.         else
  178.         {
  179.             new_node = create(data);
  180.             if(new_node)
  181.             {
  182.                 temp->right = new_node;
  183.                 printf("\n* Node with data %d was inserted", data);
  184.             }
  185.             return;
  186.         }
  187.     }
  188. }
  189.  
  190. void delete(int key)
  191. {
  192.     // Tree is empty
  193.     if(root == NULL)
  194.     {
  195.         return;
  196.     }
  197.  
  198.     // Tree having only one node
  199.     if(root->left == NULL && root->right == NULL)
  200.     {
  201.         if(root->val == key)
  202.         {
  203.             root = NULL;
  204.             printf("\n* Node with data %d was deleted", key);
  205.             return;
  206.         }
  207.         else
  208.         {
  209.             return;
  210.         }
  211.     }
  212.  
  213.     // level order traversal using the queue
  214.     struct TreeNode* temp = NULL, *last_node = NULL, *key_node = NULL;
  215.  
  216.     struct TreeNode* queue[MAX_SIZE];
  217.     int front = -1;
  218.     int rear = -1;
  219.  
  220.     queue[front + 1] = root;
  221.     front = rear = 0;
  222.  
  223.     // do level order traversal to find the deepest node
  224.     while (front <= rear)
  225.     {
  226.         temp = queue[front];
  227.         front++;
  228.  
  229.         if (temp->val == key)
  230.         {
  231.             key_node = temp;
  232.         }
  233.  
  234.         if (temp->left != NULL)
  235.         {
  236.             last_node = temp;
  237.             queue[++rear] = temp->left;
  238.         }
  239.  
  240.         if (temp->right != NULL)
  241.         {
  242.             last_node = temp;
  243.             queue[++rear] = temp->right;
  244.         }
  245.     }
  246.  
  247.     // if key is found in the binary tree
  248.     if (key_node != NULL)
  249.     {
  250.         // replace the keynode data with the deepest node
  251.         key_node->val = temp->val;
  252.  
  253.         // free the last node after updating its parent
  254.         if (last_node->right == temp)
  255.         {
  256.             last_node->right = NULL;
  257.         }
  258.         else
  259.         {
  260.             last_node->left = NULL;
  261.         }
  262.         printf("\n* Node with data %d was deleted", key);
  263.         free(temp);
  264.         return;
  265.     }
  266.     printf("\n* Node with data %d was not found", key);
  267. }   
  268.  
  269. int search(int key)
  270. {
  271.     if (root == NULL)
  272.     {
  273.         return -1;
  274.     }
  275.     struct TreeNode* queue[MAX_SIZE];
  276.     int front = -1;
  277.     int rear = -1;
  278.  
  279.     queue[front + 1] = root;
  280.     front = rear = 0;
  281.  
  282.     // do level order traversal to find the deepest node
  283.     while (front <= rear)
  284.     {
  285.         struct TreeNode* temp = queue[front];
  286.         front++;
  287.  
  288.         if (temp->val == key)
  289.         {
  290.             return 1;
  291.         }
  292.  
  293.         if (temp->left != NULL)
  294.         {
  295.             queue[++rear] = temp->left;
  296.         }
  297.  
  298.         if (temp->right != NULL)
  299.         {
  300.             queue[++rear] = temp->right;
  301.         }
  302.     }
  303.     return -1;
  304. }
  305.  
  306. int height(struct TreeNode* root)
  307. {
  308.     if (root == NULL)
  309.     {
  310.         return 0;
  311.     }
  312.  
  313.     int left = height(root->left);
  314.     int right = height(root->right);
  315.  
  316.     if(left > right)
  317.     {
  318.         return left + 1;
  319.     }
  320.     else
  321.     {
  322.         return right + 1;
  323.     }
  324. }
  325.  
  326. // inorder traversal
  327. void inorder(struct TreeNode* root)
  328. {
  329.     if(root == NULL) return;
  330.  
  331.     inorder(root->left);
  332.     printf("%d ", root->val);
  333.     inorder(root->right);
  334. }
  335.  
  336. // preorder traversal
  337. void preorder(struct TreeNode* root)
  338. {
  339.     if(root == NULL) return;
  340.  
  341.     printf("%d ", root->val);
  342.     preorder(root->left);
  343.     preorder(root->right);
  344. }
  345.  
  346. // postorder traversal
  347. void postorder(struct TreeNode* root)
  348. {
  349.     if(root == NULL) return;
  350.  
  351.     postorder(root->left);
  352.     postorder(root->right);
  353.     printf("%d ", root->val);
  354. }
  355.  
  356. // level order traversal
  357. void levelorder()
  358. {
  359.     if (root == NULL)
  360.     {
  361.         printf("Tree is Empty!");
  362.         return;
  363.     }
  364.  
  365.     struct TreeNode* queue[MAX_SIZE];
  366.     int front = -1;
  367.     int rear = -1;
  368.  
  369.     queue[front + 1] = root;
  370.     front = rear = 0;
  371.  
  372.     // do level order traversal to find the deepest node
  373.     while (front <= rear)
  374.     {
  375.         struct TreeNode* temp = queue[front];
  376.         front++;
  377.  
  378.         printf("%d ", temp->val);
  379.  
  380.         if (temp->left != NULL)
  381.         {
  382.             queue[++rear] = temp->left;
  383.         }
  384.  
  385.         if (temp->right != NULL)
  386.         {
  387.             queue[++rear] = temp->right;
  388.         }
  389.     }
  390. }
Program Explanation

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

Insert a New Node in the Binary Tree
advertisement

Insertion is the method to add a new node in the Binary Tree. We are traversing the binary tree in level order so that we can balance the binary tree on insertion at each level.

  1. Start traversing the tree from the root node in level order.
  2. Insert the node at the left children of a node, If the left child of a node is NULL.
  3. If the left child is not NULL then check for the right child, Insert the node at the right of the node.
  4. Exit.

Example: Let’s insert the given nodes in the Binary Tree.
Nodes = [89, 56, 45, 2, 55]

Step 1: Insert a new node 89.

Binary Tree - Insert a new node 89

Step 2: Insert a new node 56.

Binary Tree - Insert a new node 56

Step 3: Insert a new node 45.

Binary Tree - Insert a new node 45

Step 4: Insert a new node 2.

Binary Tree - Insert a new node 2

Step 5: Insert a new node 55.

Binary Tree - Insert a new node 55

Time Complexity: O(n)
We need to traverse each node in level order to find the right position to insert the new node in a binary tree.

Space Complexity: O(n)
Since we are using the queue to store the tree nodes.

Run Time Testcases

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

 
--- Binary Tree -- 
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal  
6. Preorder Traversal 
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 1
 
Enter data for new node: 89
 
 * Node with data 89 was inserted
 
Do you want to continue? (Y/N) y
 
--- Binary Tree --
 
1. Insert         
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 1
 
Enter data for new node: 56
 
* Node with data 56 was inserted
 
Do you want to continue? (Y/N) y
 
--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 1
 
Enter data for new node: 45
 
* Node with data 45 was inserted
 
Do you want to continue? (Y/N) y
 
--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 1
 
Enter data for new node: 2
 
* Node with data 2 was inserted
 
Do you want to continue? (Y/N) y
 
--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 1
 
Enter data for new node: 55
 
* Node with data 55 was inserted
 
Do you want to continue? (Y/N) n

Delete a Node from the Binary Tree

To delete the node from the tree requires following the given steps:

  1. Traverse the tree to find the node which has the given key.
  2. Traverse to find the deepest node.
  3. Update the data of the key node to the deepest node and then delete the deepest node.

Example: Delete node 34 in the given tree.

Delete a node from the given binary tree

The deepest leftmost node is 55. So replace the deepest node value with the key node.

Binary Tree Delete Method - Replace the deepest node value with the key node

Now delete the deepest node.

Delete the deepest node from the given binary tree

Time Complexity: O(n)
To delete the deepest node we have to traverse the entire tree of size n, where n is the number of nodes in the tree.

Space Complexity: O(n)
Since we are using the queue for the level order traversal. In the worst case, the space depends on the number of nodes in the tree, which is n.

Run Time Testcases

In this case, we are deleting the nodes in binary tree.
Note: The data in the Binary Tree are {89 56 45 2 55}

 
--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 8
 
Level order Traversal
 
89 56 45 2 55 
 
Do you want to continue? (Y/N) y
 
--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 2
Enter node data: 56
* Node with data 56 was deleted
 
Do you want to continue? (Y/N) y
 
--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 8
 
Level order Traversal
 
89 55 45 2
 
Do you want to continue? (Y/N) n

Searching a Node in a Binary Tree

To search a node with the given key we use the level order traversal. Searching a node in a Binary tree needs to follow the given steps:

  • Compare the key with each node value and if found the key then return 1 else return -1.

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

Push the root node into the stack and compare it with the key.

Binary Tree - Push the root node into the stack and compare it with the key

Since, 20 is not equal to 15 so we will push its children and check the data for the other nodes.

Bianry tree search method example

The data of the left child of the root node is equal to the key so we have found the key then return 1.

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

Space Complexity: O(n)
We are storing the nodes in the queue so in the worst case it takes the linear amount of space.

Run Time Testcases

In this case, we are searching the nodes in binary tree.
Note: The data in the Binary Tree are {89 56 45 2 55}

--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 8
 
Level order Traversal
 
89 56 45 2 55 
 
Do you want to continue? (Y/N) y
 
--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 3
Enter node data: 89
Node was found
 
Do you want to continue? (Y/N) y
 
--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 3
Enter node data: 89
Node not found
 
Do you want to continue? (Y/N) n

Traversals of the Binary 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.

Traversals of the Binary Tree

Inorder traversal of the tree: 89, 12, 16, 56, 76, 23

Time Complexity: O(n)
The time complexity of the inorder traversal of a binary tree is O(n). Here, n is the number of nodes. We have to traverse each node in the Binary tree.

Space Complexity: O(h)
The space complexity of the inorder traversal of a binary tree is O(h). Function calling stack requires space of stack.

Run Time Testcases

In this case, we perform an in-order traversal of the binary tree.
Note: The data in the Binary Tree are {89 56 45 2 55}

--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 5
 
Inorder Traversal
 
2 56 55 89 45 
 
Do you want to continue? (Y/N) 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 tree is given below.

Traversals of the Binary Tree

Preorder traversal of the tree: 89, 56, 2, 55, 45

Time Complexity: O(n)
The time complexity of the preorder traversal of a binary tree is O(n). Here, n is the number of nodes. We have to traverse each node in the Binary tree.

Space Complexity: O(h)
The space complexity of the preorder traversal of a binary tree is O(h). Function calling stack requires space of stack.

Run Time Testcases

In this case, we perform an preorder traversal of the binary tree.
Note: The data in the Binary Tree are {89 56 45 2 55}

--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 6
 
Preorder Traversal
 
89 56 2 55 45 
 
Do you want to continue? (Y/N) 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 tree is given below.

Traversals of the Binary Tree

Postorder traversal of the tree: 2, 55, 56, 45, 89

Time Complexity: O(n)
The time complexity of the postorder traversal of a binary tree is O(n). Here, n is the number of nodes. We have to traverse each node in the Binary tree.

Space Complexity: O(h)
The space complexity of the postorder traversal of a binary tree is O(h). Function calling stack requires space of stack.

Run Time Testcases

In this case, we perform an postorder traversal of the binary tree.
Note: The data in the Binary Tree are {89 56 45 2 55}

--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 7
 
Postorder Traversal
 
2 55 56 45 89 
 
Do you want to continue? (Y/N) y
 
--- Binary Tree --
 
1. Insert 
2. Delete
3. Search
4. Height
5. Inorder Traversal
6. Preorder Traversal
7. Postorder Traversal
8. Level order Traversal
9. Exit
 
Enter Your Choice: 4
height of the tree is: 3
 
Do you want to continue? (Y/N) n

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

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.