ADS Module4.Docx
ADS Module4.Docx
4.1 Binary tree: A Binary Tree Data Structure is a hierarchical data structure
in which each node has at most two children, referred to as the left child and the
right child. The topmost node in a binary tree is called the root, and the
bottom-most nodes are called leaves.
4.1.1 Representation of Binary Tree: Each node in a Binary Tree has three parts:
● Data
● Pointer to the left child
● Pointer to the right child
The restriction, that a node can have a maximum of two child nodes, gives us many
benefits:
● Algorithms like traversing, searching, insertion and deletion become easier
to understand, to implement, and run faster.
● Keeping data sorted in a Binary Search Tree (BST) makes searching very
efficient.
● Balancing trees is easier to do with a limited number of child nodes, using an
AVL Binary Tree for example.
● Binary Trees can be represented as arrays, making the tree more memory
efficient.
struct Node {
int data;
struct Node *left;
struct Node *right;
};
int main() {
// Initialize and allocate memory for tree nodes
struct Node* firstNode = createNode(2);
struct Node* secondNode = createNode(3);
struct Node* thirdNode = createNode(4);
struct Node* fourthNode = createNode(5);
In the Previous code, we have created four tree nodes firstNode, secondNode,
thirdNode and fourthNode having values 2, 3, 4 and 5 respectively.
● After creating three nodes, we have connected these nodes to form the tree
structure like mentioned shown in above image.
● Connect the secondNode to the left of firstNode by firstNode->left =
secondNode
● Connect the thirdNode to the right of firstNode by firstNode->right =
thirdNode
● Connect the fourthNode to the left of secondNode by secondNode->left =
fourthNode
/* Helper function that allocates a new node with the given key and NULL left
and right pointer. */
struct Node *newNode(char k)
{
struct Node *node = (struct Node*)malloc(sizeof(struct Node));
node->key = k;
node->right = node->left = NULL;
return node;
}
// If leaf node
if (root->left == NULL && root->right == NULL)
return true;
// If both left and right are not NULL, and left & right subtrees are full
if ((root->left) && (root->right))
return (isFullTree(root->left) && isFullTree(root->right));
// Driver Program
int main()
{
struct Node* root = NULL;
root = newNode(10);
root->left = newNode(20);
root->right = newNode(30);
root->left->right = newNode(40);
root->left->left = newNode(50);
root->right->left = newNode(60);
root->right->right = newNode(70);
root->left->left->left = newNode(80);
root->left->left->right = newNode(90);
root->left->right->left = newNode(80);
root->left->right->right = newNode(90);
root->right->left->left = newNode(80);
root->right->left->right = newNode(90);
root->right->right->left = newNode(80);
root->right->right->right = newNode(90);
if (isFullTree(root))
printf("The Binary Tree is full\n");
else
printf("The Binary Tree is not full\n");
return(0);
}
Disadvantages:
● Needs extra memory for pointers.
● Finding a node can take longer because you have to start from the root
and follow pointers.
Array Representation
Array Representation is another way to represent binary trees, especially useful
when the tree is complete (all levels are fully filled except possibly the last, which
is filled from left to right).
Rules to determine the locations of the parent, left child and right child of any
node I in the binary tree using array.
● Store the root node in the first location of the array TREE.
● If a node is present in the location I of the array TREE, then store its left
child in the location 2* I
● If a node is present in the location I of the array TREE, then store its right
child in the location 2* I+1.
Advantages:
● This representation is very easy to understand.
● This is the best representation for complete and full binary tree
representation.
● Programming is very easy.
● It is very easy to move from a child to its parents and vice versa.
Disadvantages:
Tree Traversal refers to the process of visiting or accessing each node of the tree
exactly once in a certain order. Tree traversal algorithms help us to visit and
process all the nodes of the tree. Since tree is not a linear data structure, there are
multiple nodes which we can visit after visiting a certain node.
A Tree Data Structure can be traversed in following ways:
● Depth First Search or DFS
o Inorder Traversal
o Preorder Traversal
o Postorder Traversal
● Level Order Traversal or Breadth First Search or BFS
1. Inorder traversal visits the node in the order: Left -> Root -> Right
2. Preorder traversal visits the node in the order: Root -> Left -> Right
3.Postorder traversal visits the node in the order: Left -> Right -> Root
4.Level Order Traversal visits all nodes present in the same level completely
before visiting the next level.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* left;
struct Node* right;
};
int main() {
struct Node* root = newNode(2);
root->left = newNode(1);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printf("In-Order Traversal: ");
inOrderTraversal(root);
printf("\n");
return 0;
}
struct Node {
int data;
struct Node* left;
struct Node* right;
};
int main() {
// Create the following binary tree
// 1
// / \
// 2 3
// / \
// 4 5
return 0;
}
Output Pre-Order Traversal: 1 2 4 5 3
struct Node {
int data;
struct Node* left;
struct Node* right;
};
int main () {
// Create the following binary tree
// 1
// / \
// 2 3
// / \
// 4 5
return 0;
}
Output Post-Order Traversal: 4 5 2 3 1
4.6 Binary Search Tree: A BST is a type of Binary Tree data structure,
where the following properties must be true for any node "X" in the tree:
● The X node's left child and all of its descendants (children, children's
children, and so on) have lower values than X's value.
● The right child, and all its descendants have higher values than X's value.
● Left and right subtrees must also be Binary Search Trees.
These properties make it faster to search, add and delete values than a regular
binary tree.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int key;
struct Node* left;
struct Node* right;
};
// Driver Code
int main()
{
// Creating a hard coded tree for keeping
// the length of the code small. We need
// to make sure that BST properties are
// maintained if we try some other cases.
struct Node* root = newNode(50);
root->left = newNode(30);
root->right = newNode(70);
root->left->left = newNode(20);
root->left->right = newNode(40);
root->right->left = newNode(60);
root->right->right = newNode(80);
return 0;
}
Output Not Found
Found
4.6.2 Insertion in Binary Search Tree (BST):
A new key is always inserted at the leaf by maintaining the property of the binary
search tree. We start searching for a key from the root until we hit a leaf node.
Once a leaf node is found, the new node is added as a child of the leaf node. The
below steps are followed while we try to insert a node into a binary search tree:
● Initialize the current node (say, currNode or node) with root node.
● Compare the key with the current node.
● Move left if the key is less than or equal to the current node value.
● Move right if the key is greater than current node value.
● Repeat steps 2 and 3 until you reach a leaf node.
● Attach the new key as a left or right child based on the comparison with
the leaf node’s value.
// Otherwise, recur down the tree. If the key to be inserted is greater than the
//node's key,insert it in the right subtree
if (node->key < key)
node->right = insert(node->right, key);
// If the key to be inserted is smaller than the node's key,insert it in the left
//subtree
else
node->left = insert(node->left, key);
return 0;
}
Output 20 30 40 50 60 70 80
Insertion in Binary Search Tree using Iterative approach:
#include <stdio.h>
#include <stdlib.h>
// If tree is empty
if (root == NULL)
return temp;
// Find the node who is going to have the new node temp as
// it child. The parent node is mainly going to be a leaf node
struct Node *parent = NULL, *curr = root;
while (curr != NULL) {
parent = curr;
if (curr->key > x)
curr = curr->left;
else if (curr->key < x)
curr = curr->right;
else
return root;
}
Case 2. Delete a Node with Single Child in BST: Deleting a single child node is
also simple in BST. Copy the child to the node and delete the node.
Case 3. Delete a Node with Both Children in BST:
Deleting a node with both children is not so simple. Here we have to delete the
node is such a way, that the resulting tree follows the properties of a BST. The trick
is to find the inorder successor of the node. Copy contents of the inorder successor
to the node and delete the inorder successor.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int key;
struct Node* left;
struct Node* right;
};
// Note that it is not a generic inorder successor function. It mainly works when
//the right child is not empty, which is the case we need in BST delete.
struct Node* getSuccessor(struct Node* curr) {
curr = curr->right;
while (curr != NULL && curr->left != NULL)
curr = curr->left;
return curr;
}
// This function deletes a given key x from the given BST and returns the
//modified root of the BST (if it is modified)
struct Node* delNode(struct Node* root, int x) {
// Base case
if (root == NULL)
return root;
// 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;
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
};
newNode->data = value;
return newNode;
if (root == NULL)
return createNode(value);
return root;
return root;
else
root = root->left;
return root;
}
if (root == NULL)
return root;
else {
// Node found
if (root->left == NULL) {
free(root);
return temp;
free(root);
return temp;
}
// Node with two children
root->data = temp->data;
return root;
// Inorder traversal
if (root != NULL) {
inorder(root->left);
inorder(root->right);
// Main function
int main() {
while (1) {
scanf("%d", &choice);
switch (choice) {
case 1:
scanf("%d", &value);
break;
case 2:
scanf("%d", &value);
break;
case 3:
printf("Enter value to search: ");
scanf("%d", &value);
if (search(root, value))
else
break;
case 4:
inorder(root);
printf("\n");
break;
case 5:
printf("Exiting program.\n");
exit(0);
default:
return 0;
}
Output :
1. Insert
2. Delete
3. Search
4. Inorder Traversal
5. Exit
Enter choice: 1
1. Insert
2. Delete
3. Search
4. Inorder Traversal
5. Exit
Enter choice: 4
Inorder Traversal: 2
4.7 Threaded Binary Tree:
A threaded binary tree is a type of binary tree data structure where the empty left
and right child pointers in a binary tree are replaced with threads that link nodes
directly to their in-order predecessor or successor, thereby providing a way to
traverse the tree without using recursion or a stack.
There are two types of threaded binary trees.
● Every node in threaded binary tree needs extra information (extra memory)
to indicate whether its left or right node indicated its child nodes or its
inorder predecessor or successor. So, the node consumes extra memory to
implement.
● Insertion and deletion are way more complex and time consuming than the
normal one since both threads and ordinary links need to be maintained.
● Implementing threads for every possible node is complicated.
a[]= “*+ab-cd”
Approach: If the character is an operand i.e. X then it’ll be the leaf node of the
required tree as all the operands are at the leaf in an expression tree. Else if the
character is an operator and of the form OP X Y then it’ll be an internal node with
left child as the expression Tree(X) and right child as the expression Tree(Y) which
can be solved using a recursive function.
● For max-heap, it makes sure the maximum element is the root of that binary
tree and all descendants also follow the same property.
● For min-heap, it balances in such a way that the minimum element is the
root and all descendants also follow the same property.
4.9.1 Insertion: When a new element is inserted into the heap, it can disrupt
the heap’s properties. To restore and maintain the heap structure, a heapify
operation is performed. This operation ensures the heap properties are preserved
Examples:
4.9.2 Deletion: If we delete the element from the heap, it always deletes the
root element of the tree and replaces it with the last element of the tree. Since we
delete the root element from the heap it will distort the properties of the heap, so
we need to perform heapify operations so that it maintains the property of the heap.
Example:
Question bank
1. What is a Binary Tree? Explain its properties.
2. Define Strictly Binary Tree and Complete Binary Tree with examples.
3. How is a binary tree represented in memory? Explain with an example.
4. Explain binary tree traversals (Inorder, Preorder, Postorder) with an
example.
5. Write a C program to implement Preorder traversal of a binary tree.
6. What is a Binary Search Tree (BST)? Explain its properties.
7. Write the algorithm for inserting an element into a Binary Search Tree
(BST).
8. Write the algorithm for deleting a node from a Binary Search Tree (BST).
9. What is a Threaded Binary Tree? Explain its advantages.
10.Define Expression Tree. How is it useful in expression evaluation?
11.Write a C program to insert a node into a Binary Search Tree (BST).
12.Implement a C program to perform Inorder, Preorder, and Postorder traversal
of a binary tree.
13.Write a C program to delete a node from a Binary Search Tree (BST).
14.Explain the construction of an expression tree from a prefix and postfix
expression with an example.
15.Write a C program to construct an Expression Tree from a given postfix
expression.
16.What is a Heap Tree? Explain Min Heap and Max Heap with examples.
17.Write a C program to create a Heap Tree using an array.
18.Explain Insertion in a Heap and write the algorithm for inserting an element
into a heap.
19.Write a C program to insert an element into a Max Heap and maintain heap
properties.
20.Explain Deletion from a Heap and write an algorithm for deleting an
element from a heap.
21.Write a C program to construct and traverse a Binary Tree using recursion.
22.Implement a C program to insert, delete, and search elements in a Binary
Search Tree (BST).
23.Write a C program to convert a prefix and postfix expression into an
Expression Tree and evaluate it.
24.Implement a C program to create and traverse a Threaded Binary Tree.
25.Write a C program to insert an element into a Heap Tree and maintain the
heap structure.
26.Implement a C program to delete the root node from a Heap Tree and restore
heap properties.
27.Explain Heap Sort with an example. Implement Heap Sort in C.
28.Implement a C program to perform Level Order Traversal of a binary tree
using a queue.
29.Compare Binary Search Tree, Heap Tree, and Threaded Binary Tree based
on their properties and applications.
30.Write a C program to implement a priority queue using a heap.
C programs:
● Write a C program to create a binary tree using dynamic memory allocation.
● Implement a C program to traverse a binary tree using Preorder Traversal.
● Write a C program to traverse a binary tree using Inorder Traversal.
● Implement a C program to traverse a binary tree using Postorder Traversal.
● Write a C program to check if a given binary tree is a Strictly Binary Tree.
● Implement a C program to check if a given binary tree is a Complete Binary
Tree.
● Write a C program to insert a node into a Binary Search Tree (BST).
● Implement a C program to search for a given key in a Binary Search Tree
(BST).
● Write a C program to represent a Binary Tree in memory using linked
representation.
● Implement a C program to construct an Expression Tree from a Postfix
Expression.
● Write a C program to construct and display a Binary Search Tree (BST).
● Implement a C program to delete a node from a Binary Search Tree (BST).
● Write a C program to check whether a given binary tree is Balanced or Not.
● Implement a C program to construct an Expression Tree from a Prefix
Expression.
● Write a C program to evaluate a Postfix Expression using an Expression
Tree.
● Implement a C program to create a Threaded Binary Tree and perform
Inorder traversal.
● Write a C program to create a Heap Tree and insert elements into it.
● Implement a C program to delete an element from a Max Heap.
● Write a C program to implement a Min Heap and perform insertion and
deletion operations.
● Implement a C program to convert a BST into a Balanced BST.
● Write a C program to implement all three tree traversals (Inorder, Preorder,
Postorder) in a Binary Tree.
● Implement a C program to insert, delete, and search elements in a Binary
Search Tree (BST).
● Write a C program to construct and evaluate an Expression Tree from a
Postfix Expression.
● Implement a C program to construct and evaluate an Expression Tree from a
Prefix Expression.
● Write a C program to implement a Threaded Binary Tree and perform
traversal without recursion.
● Implement a C program to create a Heap Tree, insert elements, and maintain
heap properties.
● Write a C program to delete the root node from a Heap Tree and restructure
the heap.
● Implement a C program for Heap Sort using a Min Heap or Max Heap.
● Write a C program to convert a Binary Tree into its Mirror Image.
● Implement a C program to find the Lowest Common Ancestor (LCA) of two
nodes in a Binary Search Tree.