0% found this document useful (0 votes)
17 views

5.trees (Finalized)

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

5.trees (Finalized)

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 119

Trees:

Qns:

Tree Terminology:
A tree is a hierarchical data structure defined as a
collection of nodes. Nodes represent value and nodes are connected by edges.
The tree has one node called root.

Root:

The root node is the topmost node in the tree hierarchy. In other words,
the root node is the one that doesn't have any parent. In the below structure,
node numbered A is the root node of the tree. If a node is directly linked to
some other node, it would be called a parent-child relationship.
Child node:

If the node is a descendant of any node, then the node is known as a


child node. A "child node" is a node that is directly connected to another node
called its "parent node." The relationship indicates that the child node is a sub-
element or subordinate to the parent node.

Parent:

If the node contains any sub-node, then that node is said to be the parent
of that sub-node. Or A node that has one or more child nodes directly connected
to it. The node which is a predecessor of any node is called a Parent Node, that
is, the node which has a branch from it to any other node is called as the Parent
node.
Sibling:

The nodes that have the same parent are known as siblings. In a tree
data structure, nodes which belong to same Parent are called as SIBLINGS. In
simple words, the nodes with the same parent are called Sibling nodes.

Leaf Node:

The node of the tree, which doesn't have any child node, is called a
leaf node. A leaf node is the bottom-most node of the tree. There can be any
number of leaf nodes present in a general tree. Leaf nodes can also be called
external nodes.
Internal nodes:

A node has at least one child node known as an internal node. An


internal node (also known as an inner node, node for short, or branch node)
is any node of a tree that has child nodes. Similarly, an external node (also
known as an outer node, leaf node, or terminal node) is any node that does not
have child nodes.

Ancestor node:

An ancestor of a node is any predecessor node on a path from


the root to that node. The root node doesn't have any ancestors. In the tree shown
in the below image, nodes 1, 3, and 7 are the ancestors of node 11.
Descendant:

The immediate successor of the given node is known as a descendant


of a node. In the above figure, 10 is the descendant of node 5.

Degree of a Node:

The degree of a node is the total number of branches of that


node. In the tree data structure, the total number of children of a node is called
the degree of the node. The highest degree of the node among all the nodes in a
tree is called the Degree of Tree.
struct node
{
int data;
struct node *left;
struct node *right;
}

Qns:

Array and linked Representation of Binary Trees:

A binary tree data structure is represented using two methods. Those methods are
as follows...

1. Array Representation
2. Linked List Representation

1. Array Representation of Binary Tree:


In array representation of a binary tree, we use one-dimensional
array (1-D Array) to represent a binary tree.
Consider the above example of a binary tree and it is represented as follows...
2. Linked List Representation of Binary Tree:

We use a double linked list to


represent a binary tree. In a double linked list, every node consists of three
fields. First field for storing left child address, second for storing actual data and
third for storing right child address.
Qns:

Binary Tree:

A Binary Tree is a type of tree data structure where each node can
have a maximum of two child nodes, a left child node and a right child node.

This 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.
A binary tree is a fundamental data structure in computer science, characterized
by the following properties:

Nodes: A binary tree consists of nodes. Each node contains three parts:

Data: The value stored in the node.


Left Child: A reference (or pointer) to the left child node.
Right Child: A reference (or pointer) to the right child node.

Root: The top node of the binary tree is called the root. It is the only node that
has no parent.

Leaves: Nodes that do not have any children are called leaves or leaf nodes.

Parent and Child: In a binary tree, every node (except the root) has exactly one
parent. Each node can have at most two children: a left child and a right child.

Height: The height of a binary tree is the length of the longest path from the
root to a leaf. The height of a tree with only one node (the root) is 0.
Types of Binary Trees:

Full Binary Tree: A tree in which every node has either zero children or two
children, Every node other than the leaves has two children.

Perfect Binary Tree: All internal nodes have two children, and all leaf nodes
are at the same level or a binary tree in which all interior nodes have two
children and all leaves have the same depth or same level
Complete Binary Tree:

All levels are completely filled except possibly for the


last level, which is filled from left to right.

Balanced Binary Tree: A binary tree is balanced if the height difference


between the left and right subtrees of any node is at most one.
Degenerate (or Pathological) Tree:

A binary tree where each parent node has


only one child. A Tree where every internal node has one child. Such trees are
performance-wise same as linked list. A degenerate or pathological tree is a tree
having a single child either left or right. This structure resembles a linked list.
Qns:

Binary Tree Traversal Methods:

What is binary tree traversal in data structure?


Traversal is a technique for
visiting all of a tree's nodes and printing their values. Traversing a tree involves
iterating over all nodes in some manner. We always start from the root (head)
node since all nodes are connected by edges (links).

In-order Traversal: Left subtree → Node → Right subtree.


Pre-order Traversal: Node → Left subtree → Right subtree.
Post-order Traversal: Left subtree → Right subtree → Node.
Level-order Traversal: Nodes are visited level by level, starting from the
root.

In-order Traversal (L-P-R):


In this traversal method, the left subtree is visited
first, then the root and later the right sub-tree. We should always remember that
every node may represent a subtree itself. If a binary tree is traversed in-order,
the output will produce sorted key values in an ascending order.
H – D – I – B – E – A - F- J - C- G
Pre-order Traversal (P-L-R):
Preorder traversal is defined as a type of tree
traversal that follows the Root-Left-Right policy where: The root node of the
subtree is visited first. Then the left subtree is traversed. At last, the right subtree
is traversed.
A-B-D-H-I-E-C-F-J-G

Post - Order Traversal(L-R-P):

Post order traversal is defined as a type of tree


traversal which follows the Left-Right-Root policy such that for each node: The
left subtree is traversed first. Then the right subtree is traversed. Finally, the root
node of the subtree is traversed.
H-I-D-E-B-J-F=G-C-A

Applications of Binary Search Tree:

Binary trees are widely used in various applications, including:

Binary Search Trees (BST): A type of binary tree used for efficient searching,
insertion, and deletion.

Heaps: A binary tree used to implement priority queues.

Expression Trees: Used to represent arithmetic expressions.

Huffman Coding Trees: Used in data compression algorithms.

Binary trees are a versatile and foundational data structure in computer science,
providing the basis for many more advanced structures and algorithms.
Example:

#include <stdio.h>
#include <stdlib.h>
typedef struct Node // Define the structure for a node in the binary tree
{
int data;
struct Node *left, *right;
} Node;

Node* createNode(int data) // Function to create a new node


{
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}

// Function to perform in-order traversal (Left, Root, Right)


void inorderTraversal(Node* root) //(L-P-R)
{
if (root == NULL)
return;
inorderTraversal(root->left);
printf("%d ", root->data);
inorderTraversal(root->right);
}
// Function to perform pre-order traversal (Root, Left, Right)
void preorderTraversal(Node* root) //(P-L-R)
{
if (root == NULL)
return;
printf("%d ", root->data);
preorderTraversal(root->left);
preorderTraversal(root->right);
}

// Function to perform post-order traversal (Left, Right, Root)


void postorderTraversal(Node* root) //L-R-P
{
if (root == NULL)
return;
postorderTraversal(root->left);
postorderTraversal(root->right);
printf("%d ", root->data);
}

int main()
{
Node* root = createNode (1);
root ->left = createNode (2);
root->right = createNode (3);
root ->left->left = createNode (4);
root ->left->right = createNode (5);
root ->right->left = createNode (6);
root ->right->right = createNode (7);
printf ("In-order traversal: ");
inorderTraversal(root);
printf("\n");

printf ("Pre-order traversal: ");


preorderTraversal(root);
printf("\n");

printf ("post-order traversal: ");


postorderTraversal(root);
printf("\n");
return 0;
}

Output:
In-order traversal: 4 2 5 1 6 3 7
Pre-order traversal: 1 2 4 5 3 6 7
Post-order traversal: 4 5 2 6 7 3 1
Qns:

What is 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

Types of Threaded Binary Tree:

Threaded Binary tree classified into Two types.

1. One-way threaded Binary Tree / Single Threaded


2. Two-way threaded Binary Tree / Double Threaded
Single threaded Binary Tree / One-way:

Single-Threaded Binary Trees: Each


node contains a link to its in-order successor or predecessor in single-threaded
binary trees. However, the link to the other node (predecessor or successor)
remains as a null pointer.

In one-way threaded binary trees, a thread will appear either in the right
or left link field of a node.
If it appears in the right link field of a node then it will point to the next
node that will appear on performing in order traversal.
Such trees are called Right threaded binary trees.
If thread appears in the left field of a node, then it will point to the nodes
in order predecessor.
Such trees are called Left threaded binary trees.
In one-way threaded binary trees, the right link field of last node and left
link field of first node contains a NULL.
In order to distinguish threads from normal links they are represented by
dotted lines.
Double threaded Binary trees / Two-way:

Two-way threaded Binary trees, the right


link field of a node containing NULL values is replaced by a thread that points
to nodes in-order successor and left field of a node containing NULL values is
replaced by a thread that points to nodes in-order predecessor.

Difference between Binary Tree and Binary Threaded Tree:

Binary trees have a lot of wasted space.


The leaf nodes each have 2 null pointers.
We can use these pointers to help us in in-order traversals.
Threaded binary tree makes the tree tra- versal faster since we do not
need stack or recursion for traversal.
What is the need for a Threaded Binary Tree:

Space Optimization:

Threaded Binary Trees make use of null pointers to store


the in-order predecessor and successor, reducing the space complexity that
would otherwise be used by stacks in traversal.

Time Efficiency:

By threading the nodes, it eliminates the need to backtrack to


ancestors, making in-order traversal faster and more efficient.

Simplification of Tree Operations:

Operations like insertion, deletion, and


traversal become more straightforward because the tree inherently maintains a
sort of "memory" of the node sequence.

Non-recursive Traversals: It allows for non-recursive in-order or pre-order


traversals, which can be advantageous in environments where stack size is
limited or recursion is costly in terms of performance.

1-Way Threaded 2-Way Threaded

struct Node struct Node

{ {

int value; int value;


Node* left; Node* left;
Node* right; Node* right;
bool rightThread; bool leftThread;
bool rightThread;
} }
}
Example:

#include <stdio.h>

#include <stdlib.h>

typedef struct Node

int data;

struct Node* left;

struct Node* right;

int leftThread; // 1 if left child is a thread, 0 otherwise

int rightThread; // 1 if right child is a thread, 0 otherwise

} Node;

Node* createNode(int data)

Node* newNode = (Node*) malloc(sizeof(Node));

if (!newNode)

printf("Memory error\n");

return NULL;

newNode->data = data;

newNode->left = newNode->right = NULL;

newNode->leftThread = newNode->rightThread = 0;
return newNode;

Node* insertNode(Node* root, int data)

if (root == NULL) // If the tree is empty, create a new node

root = createNode(data);

return root;

if (data < root->data) // Recursively insert data into the left or right subtree

if (root->leftThread)

Node* newNode = createNode(data); // If left child is a thread, replace it with


the new node

newNode->left = root->left;

newNode->right = root;

newNode->rightThread = 1;

root->left = newNode;

root->leftThread = 0;

else
{

root->left = insertNode(root->left, data);

else if (data > root->data)

if (root->rightThread)

Node* newNode = createNode(data); // If right child is a thread, replace it with the new node

newNode->right = root->right;

newNode->left = root;

newNode->leftThread = 1;

root->right = newNode;

root->rightThread = 0;

else

root->right = insertNode(root->right, data);

return root;

}
void inorderTraversal(Node* root) // Function to perform in-order traversal

if (root != NULL)

if (!root->leftThread) // Traverse left subtree

inorderTraversal(root->left);

printf("%d ", root->data); // Print current node

if (!root->rightThread) // Traverse right subtree

inorderTraversal(root->right);

int main()

Node* root = NULL;

root = insertNode(root, 50);

root = insertNode(root, 30);

root = insertNode(root, 20);

root = insertNode(root, 40);


root = insertNode(root, 70);

root = insertNode(root, 60);

root = insertNode(root, 80);

printf("Threaded Binary Tree (inorder traversal):\n");

inorderTraversal(root);

printf("\n");

return 0;

Output:

Threaded Binary Tree (in-order traversal):

20 30 40 50 60 70 80
Qns:

Binary Search Tree:

A Binary Search Tree (BST) is a type of binary tree that is


used to efficiently store and manage data, particularly when it comes to
searching, insertion, and deletion operations. In binary Search Tree smaller than
values are inserted into left sub-tree and greater than values are inserted into
right sub-tree.

In the above figure, the root node is 40, and all the nodes of the left subtree are
smaller than the root node, and all the nodes of the right subtree are greater
than the root node.

Implementation:

First, compare the element to be searched with the root element of the tree.
If root is matched with the target element, then return the node's location.
If it is not matched, then check whether the item is less than the root
element or smaller than the root element, then move to the left subtree.
If it is larger than the root element, then move to the right subtree.
Repeat the above procedure recursively until the match is found.
If the element is not found or not present in the tree, then return NULL.
Characteristics of Binary Search Tree:

1.Binary Tree Structure: A binary tree is a tree data structure where each node
has at most two children, referred to as the left child and the right child.

2. Node Properties:
Left Subtree:
All nodes in the left subtree of a node contain values that are less than the value
of the node.
Right Subtree: All nodes in the right subtree of a node contain values that are
greater than the value of the node.

Unique Values: Generally, BSTs contain unique values, so no duplicate values


are present in the tree.

3.Operations:

1.Insertion:

To insert a value, follow the same procedure as searching: traverse


the tree starting from the root, and insert the new value as a leaf node in the
appropriate position (left or right) where it maintains the BST property.

2.Deletion:

Deleting a node in a BST can be a bit more complex because there are three
cases to consider:

Node with no children (leaf node): Simply remove the node.

Node with one child: Remove the node and link its parent directly to its child.

Node with two children: Find the node's in-order predecessor (maximum value
in the left subtree) or in-order successor (minimum value in the right subtree),
replace the node's value with that, and then delete the in-order
predecessor/successor node.
3.Search:

To search for a value in a BST, start from the root and recursively
traverse the left or right subtree depending on whether the target value is
less than or greater than the current node's value.
The average time complexity for searching in a BST is O(log n) if the
tree is balanced.

Advantages:

Efficient Search: BSTs provide an efficient way to search for elements,


especially when the tree is balanced, achieving O(log n) time complexity.

Ordered Structure: The in-order traversal of a BST results in a sorted


sequence of values.

Disadvantages:

Balancing Issues: If the BST becomes unbalanced (e.g., all elements are
inserted in increasing or decreasing order), the time complexity for operations
can degrade to O(n),which is the same as a linked list.

Binary Search Tree Operations:

Basic operations on a BST

Create: creates an empty tree.

Insert: insert a node in the tree.

Delete: deletes a node from the tree.

Search: Searches for a node in the tree.

In order: in-order traversal of the tree.

Preorder: pre-order traversal of the tree.

Post order: post-order traversal of the tree.


Qns:

Implementation:

Example: 45, 15, 79, 90, 10, 55, 12, 20, 50

First insert 45 into the tree as the root of the tree.


Then, read the next element.
if it is smaller than the root node, insert it as the root of the left subtree,
and move to the next element.
if the element is larger than the root node, then insert it as the root of the
right subtree.

45

Step:1

Insert 15, 15 is smaller than 45, so insert it as the root node of the left subtree.

45

15
Step:2

Insert 79, 79 is greater than 45, so insert it as the root node of the right subtree.

45

Step:3
15 79
Insert 90.
90 is greater than 45 and 79, so it will be inserted as the right subtree of 79.

45

15 79

90
Step:4

Insert 10.

10 is smaller than 45 and 15, so it will be inserted as a left subtree of 15.

45

15 79

10 90
Step 5:

Insert 55.

55 is larger than 45 and smaller than 79, so it will be inserted as the left subtree
of 79.

45

15 79

10 55 90

Step 6:

Insert 12.

12 is smaller than 45 and 15 but greater than 10, so it will be inserted as the right
subtree of 10.

45

15 79

10 55 90

12
Step 7:

Insert 20.

20 is smaller than 45 but greater than 15, so it will be inserted as the right subtree
of 15.

45

15 79

10 20 55 90

12
Step :8

Insert 50.

50 is greater than 45 but smaller than 79 and 55. So, it will be inserted as a left
subtree of 55.

45

15 79

10 20 55 90

12 50
Example:

Example:

#include <stdio.h>

#include <stdlib.h>

struct Node

int data;

struct Node* left;

struct Node* right;

};

struct Node* createNode(int data)

struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));

newNode->data = data;

newNode->left = NULL;

newNode->right = NULL;

return newNode;

struct Node* insert(struct Node* root, int data)

if (root == NULL)

{
return createNode(data);

if (data < root->data)

root->left = insert(root->left, data);

else if (data > root->data)

root->right = insert(root->right, data);

return root;

void inorder(struct Node* root)

if (root != NULL)

inorder(root->left);

printf("%d ", root->data);

inorder(root->right);

}
int main()

struct Node* root = NULL;

root = insert(root, 50);

insert (root, 45);

insert (root, 15);

insert(root, 79);

insert (root, 10);

insert (root, 55);

insert (root, 12);

insert (root,20);

insert (root,50);

printf("In-order traversal of the BST:\n ");

inorder(root);

printf("\n");

return 0;

Output:

In-order traversal of the BST:

10 12 15 20 45 50 55 79
Deletion in Binary Search tree:

In a binary search tree, we must delete a node


from the tree by keeping in mind that the property of BST is not violated. To
delete a node from BST, there are three possible situations occur -

The node to be deleted is the leaf node,


The node to be deleted has only one child,
The node to be deleted has two children

Step:1

Delete node 90, as the node to be deleted is a leaf node, so it will be replaced
with NULL, and the allocated space will free.
Step:2

Delete node 79, the node to be deleted has only one child, so it will be replaced
with its child 55.

Step: 3

Delete node 45 that is the root node, as the node to be deleted has two
children, so it will be replaced with its in-order successor. Now, node 45 will be
at the leaf of the tree so that it can be deleted easily.
Step:4

Delete node 15

Step:5

Delete Node: 50
Step:6

Delete: Node 20

Step:7

Delete Node: 12

Step:8

Delete: Node 55

55 10

10
Step:9

Delete: Node 10

10

Finally, the tree is empty.

Difference Between Binary Tee and Binary Search Tree:

Feature Binary Tree Binary Search Tree ( BST )

A binary tree in which for each


A tree data structure
node, all elements in its left
where each node can
subtree are less than the node, and
have at most two
all elements in its right subtree are
children’s nodes.
Definition greater than the node.

Nodes are inserted Nodes are inserted according to


without any specific their values, maintaining the BST
Node Insertion order. property.

No specific order;
Efficient lookup using the binary
full tree traversal
search property, reducing the
Node may be needed to
search space by half at each step.
Lookup/Search find a node.
Example:

#include <stdio.h>

#include <stdlib.h>

struct node

int data;

struct node *left, *right;

};

struct node *newNode (int data)

struct node *temp = (struct node *) malloc (sizeof (struct node));

temp->data = data;

temp->left = temp->right = NULL;

return temp;

void inorderTraversal (struct node *root)

if (root != NULL)

inorderTraversal (root->left);

printf ("%d ", root->data);

inorderTraversal (root->right);
}

struct node *deleteNode (struct node *root, int key)

if (root == NULL)

return root;

if (key < root->data)

root->left = deleteNode (root->left, key);

else if (key > root->data)

root->right = deleteNode (root->right, key);

else

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); // it will free the memory before executing the program

return temp;

struct node *temp = root->right;

while (temp->left != NULL)

temp = temp->left;

root->data = temp->data;

root->right = deleteNode (root->right, temp->data);

return root;

int main ()

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);

printf ("Inorder traversal of the original tree: ");

inorderTraversal (root);

int key = 50;

root = deleteNode (root, key);

printf ("\n Inorder traversal after deleting: %d\n ", key);

inorderTraversal (root);

return 0;

Output:

In order traversal of the original tree: 20 30 40 50 60 70 80


In order traversal after deleting: 50
20 30 40 60 70 80
Binary Search Tree Operations (Insertion, Deletion, Traverse and Search)

Example:

#include <stdio.h>

#include <stdlib.h>

struct Node

int data;

struct Node* left;

struct Node* right;

};

struct Node* createNode(int value)

struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));

newNode->data = value;

newNode->left = NULL;

newNode->right = NULL;

return newNode;

}
struct Node* insert(struct Node* root, int value)

if (root == NULL)

return createNode(value);

if (value < root->data)

root->left = insert(root->left, value);

else if (value > root->data)

root->right = insert(root->right, value);

return root;

struct Node* search(struct Node* root, int value)

if (root == NULL || root->data == value)

return root;

}
if (value < root->data)

return search(root->left, value);

return search(root->right, value);

struct Node* delete(struct Node* root, int value)

if (root == NULL)

return root;

if (value < root->data)

root->left = delete(root->left, value);

else if (value > root->data)

root->right = delete(root->right, value);

else
{

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;

struct Node* temp = root->right;

while (temp->left != NULL)

temp = temp->left;

root->data = temp->data;

root->right = delete(root->right, temp->data);

return root;
}

void inorderTraversal (struct Node* root)

if (root == NULL)

return;

inorderTraversal(root->left);

printf("%d ", root->data);

inorderTraversal(root->right);

void preorderTraversal(struct Node* root) //(P-L-R)


{
if (root == NULL)
return;
printf("%d ", root->data);
preorderTraversal(root->left);
preorderTraversal(root->right);
}
// Function to perform post-order traversal (Left, Right, Root)
void postorderTraversal(struct Node* root) //L-R-P
{
if (root == NULL)
return;
postorderTraversal(root->left);
postorderTraversal(root->right);
printf("%d ", root->data);
}

int main()

struct Node* root = NULL;

root = insert (root, 50);

root = insert (root, 30);

root = insert (root, 20);

root = insert (root, 40);

root = insert (root, 70);

root = insert (root, 60);

root = insert (root, 80);

printf("In order traversal of the BST:\n ");

inorderTraversal(root);

struct Node* searchResult = search(root, 60);

if (searchResult != NULL)
{

printf("Element found: %d\n", searchResult->data);

else

printf("Element not found.");

root = delete (root, 20);

root = delete (root, 30);

root = delete (root, 50);

printf("In-order traversal after deletion of 20, 30, and 50: \n");

inorderTraversal(root);

printf("\n pre-order-Traversal is:\n");

preorderTraversal(root);

printf("\n post-order-Traversal is:\n");

postorderTraversal(root);

return 0;

}
Output:

In order traversal of the BST:

20 30 40 50 60 70 80

Element found: 60

In-order traversal after deletion of 20,30 and 50:

40 60 70 80

pre-order-Traversal after deletion of 20,30 and 50:

60 40 70 80

post-order-Traversal after deletion of 20,30 and 50:

40 80 70 60
Application of Tree:
Trees find applications in various fields, including file systems,
databases, network routing, artificial intelligence, syntax parsing, and
more.
They are used to organize and optimize data storage and retrieval,
implement efficient searching algorithms, and represent relationships
between entities.
The highest node in a tree that has no parent nodes is considered the root
of the tree. Every tree has a single root node.
Parent Node: A node's parent one is the node that came before it in the
tree of nodes.
Child Node: The node that is a node's direct successor is referred to as a
node's child node.
Siblings are the children of the same parent node.
Edge: Edge serves as a connecting node between the parent and child
nodes.
Leaf: A node without children is referred to as a leaf node. It is the tree's
last node. A tree may have several leaf nodes.
A node's subtree is the tree that views that specific node as the root node.
Depth: The depth of a node is the separation between it and the root
node.
Height: The height of a node is the distance between it and the subtree's
deepest node.
The maximum height of any node is referred to as the tree's height. The
height of the root node is the same as this.
Level: In the tree, a level is the number of parents that correspond to a
particular node.
Node degree: A node's degree is determined by how many children it
has.
A binary tree has (N+1) NULL nodes, where N is the total number of
nodes in the tree.
Qns:

Trees-Evaluation of Expression:

Evaluation of expressions using trees


typically involves the use of expression trees, a type of binary tree used to
represent and evaluate mathematical expressions. Each node in an expression
tree represents either an operator (e.g., +, -, *, /) or an operand (e.g., numbers or
variables).

The leaf nodes always denote the operands.


The operations are always performed on these operands.
The operator present in the depth of the tree is always at the highest
priority.
The operator, which is not much at the depth in the tree, is always at the
lowest priority compared to the operators lying at the depth.
The operand will always present at a depth of the tree; hence it is
considered the highest priority among all the operators.
In short, we can summarize it as the value present at a depth of the tree is
at the highest priority compared with the other operators present at the top
of the tree.
The main use of these expression trees is that it is used to evaluate,
analyze and modify the various expressions.

Structure of an Expression Tree:

Leaf Nodes: The leaf nodes of an expression tree are operands (e.g., constants
or variables).

Internal Nodes: The internal nodes represent operators, where each operator
node combines the results of its child nodes.
Binary Expression Tree:

This is the most common type of expression tree. Each operator node in
the tree has exactly two children.
For example, the expression a + (b * c) can be represented as…

For example:

The + operator is the left-associative and / is the right-associative.


The expression tree is a tree used to represent the various expressions.
The tree data structure is used to represent the expressional statements.
In this tree, the internal node always denotes the operators.
The expression tree is a binary tree in which each external or leaf node
corresponds to the operand and each internal or parent node corresponds to
the operators so for example expression tree for 7 + ((1+8) *3)
Practice Programs
Practice Programs

Example:1 ( In-Order)

#include<stdio.h>
#include<stdlib.h>
struct node
{
int key;
struct node *left;
struct node *right;
};

struct node *getNode(int val) //return a new node with the given value
{
struct node *newNode;
newNode = malloc (sizeof(struct node));
newNode->key = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
struct node *insertNode(struct node *root, int val)
//inserts nodes in the binary search tree
{
if(root == NULL)
return getNode(val);
if(root->key < val)
root->right = insertNode(root->right, val);
if(root->key > val)
root->left = insertNode(root->left, val);
return root;
}

void inorder (struct node *root) //inorder traversal of the binary search tree
{
if(root == NULL)
return;
inorder(root->left); //traverse the left subtree
printf("%d ",root->key); //visit the root
inorder(root->right); //traverse the right subtree
}

int main()
{
struct node *root = NULL;
int data;
char ch;
do
{
printf ("\n Select one of the operations::");
printf ("\n 1. To insert a new node in the Binary Tree");
printf("\n2.To display the nodes of the Binary Tree(via Inorder Traversal).\n");
int choice;
scanf("%d", &choice);
switch (choice)
{
case1:
printf("\n Enter the value to be inserted\n");
scanf("%d", &data);
root = insertNode(root, data);
break;
case2:
printf("\n In order Traversal of the Binary Tree::\n");
inorder(root);
break;
default:
printf("Wrong Entry\n");
break;
}
printf("\n Do you want to continue (Type y or n)\n");
scanf(" %c", &ch);
}
while (ch == 'Y'|| ch == 'y');
return 0;
}

Output:
Select one of the operations:
1. To insert a new node in the Binary Tree
2. To display the nodes of the Binary Tree (via In order Traversal).
1
Enter the value to be inserted
10
Do you want to continue (Type y or n)
y
Select one of the operations:
1. To insert a new node in the Binary Tree
2. To display the nodes of the Binary Tree(via Inorder Traversal).
1
Enter the value to be inserted
30
Do you want to continue (Type y or n)
y
Select one of the operations::
1. To insert a new node in the Binary Tree
2. To display the nodes of the Binary Tree(via Inorder Traversal).
1
Enter the value to be inserted
50
Do you want to continue (Type y or n)
y
Select one of the operations:
1. To insert a new node in the Binary Tree
2. To display the nodes of the Binary Tree(via Inorder Traversal).
1
Enter the value to be inserted
70
Do you want to continue (Type y or n)
y
Select one of the operations:
1. To insert a new node in the Binary Tree
2. To display the nodes of the Binary Tree(via Inorder Traversal).
1
Enter the value to be inserted
90
Do you want to continue (Type y or n)
y
Select one of the operations:
1. To insert a new node in the Binary Tree
2. To display the nodes of the Binary Tree(via Inorder Traversal).
1
Enter the value to be inserted
55
Do you want to continue (Type y or n)
y
Select one of the operations:
1. To insert a new node in the Binary Tree
2. To display the nodes of the Binary Tree(via Inorder Traversal).
2
Inorder Traversal of the Binary Tree::
10 30 50 55 70 90
Do you want to continue (Type y or n)
Example:2
#include <stdio.h>
#include <stdlib.h>
// A binary tree node has data, pointer to left child
struct node // and a pointer to right child
{
int data;
struct node* left;
struct node* right;
};
// Helper function that allocates a new node with the
// given data and NULL left and right pointers.
struct node* newNode(int data)
{
struct node* node= (struct node*) malloc (sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}

void printInorder(struct node* node) // Given a binary tree, print its nodes in inorder
{
if (node == NULL)
return;
printInorder(node->left); // First recur on left child
printf("%d ", node->data); // Then print the data of node
printInorder(node->right); // Now recur on right child
}
int main() // Driver code
{
struct node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printf("Inorder traversal of binary tree is: \n"); // Function call
printInorder(root);
getchar();
return 0;
}
Output:
In order traversal of binary tree is:

4 2 5 1 3
Example:3 (Pre-order Traversal (P-L-R):

#include <stdio.h>

#include <stdlib.h>

struct node

int data;

struct node* left;

struct node* right;

};

struct node* newNode(int data) // given data and NULL left and right pointers.

struct node* node= (struct node*) malloc (sizeof(struct node));

node->data = data;

node->left = NULL;

node->right = NULL;

return (node);

void printInorder(struct node* node) // Given a binary tree, print its nodes in
inorder

if (node == NULL)

return;
printInorder(node->left); // First recur on left child

printf("%d ", node->data); // Then print the data of node

printInorder(node->right); // Now recur on right child

int main() // Driver code

struct node* root = newNode(1);

root->left = newNode(2);

root->right = newNode(3);

root->left->left = newNode(4);

root->left->right = newNode(5);

printf("Inorder traversal of binary tree is \n"); // Function call

printInorder(root);

getchar();

return 0;

Output:

Inorder traversal of binary tree is

4 2 5 1 3
Example:4

#include<stdio.h>

#include<stdlib.h>

struct node

int key;

struct node *left;

struct node *right;

};

struct node *getNode(int val) //return a new node with the given value

struct node *newNode;

newNode = malloc (sizeof(struct node));

newNode->key = val;

newNode->left = NULL;

newNode->right = NULL;

return newNode;

}
struct node *insertNode(struct node *root, int val) //inserts nodes in the
binary search tree

if(root == NULL)

return getNode(val);

if(root->key < val)

root->right = insertNode(root->right, val);

if(root->key > val)

root->left = insertNode(root->left, val);

return root;

void preorder (struct node *root) //preorder traversal of the binary search tree

if(root == NULL)

return;

printf("%d ", root->key); //visit the root

preorder(root->left); //traverse the left subtree

preorder(root->right); //traverse the right subtree

}
int main()

struct node *root = NULL;

int data;

char ch;

/* Do while loop to display various options to select from to decide the input
*/

do

printf("\n Select one of the operations::");

printf("\n1. To insert a new node in the Binary Tree");

printf("\n2. To display the nodes of the Binary Tree(via Preorder


Traversal).\n");

int choice;

scanf("%d", &choice);

switch (choice)

case1:

printf("\n Enter the value to be inserted\n");

scanf("%d", &data);

root = insertNode(root, data);

break;
case2:

printf("\n Preorder Traversal of the Binary Tree::\n");

preorder(root);

break;

default:

printf("Wrong Entry\n");

break;

printf("\n Do you want to continue (Type y or n)\n");

scanf(" %c", &ch);

while (ch == 'Y'|| ch == 'y');

return 0;

Output:

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Preorder Traversal).

Enter the value to be inserted

10

Do you want to continue (Type y or n)


y

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree (via Preorder Traversal).

Enter the value to be inserted

30

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree (via Preorder Traversal).

Enter the value to be inserted

40

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Preorder Traversal).

Enter the value to be inserted


20

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Preorder Traversal).

Enter the value to be inserted

70

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Preorder Traversal).

Enter the value to be inserted

60

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Preorder Traversal).


2

Preorder Traversal of the Binary Tree::

10 30 20 40 70 60

Do you want to continue (Type y or n)


Example:5 (Post - Order Traversal(L-R-P):

#include <stdio.h>

#include <stdlib.h>

struct node

int data;

struct node* left;

struct node* right;

};

struct node* newNode(int data)


{
struct node* node= (struct node*) malloc (sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}

void printPostorder(struct node* node) // "bottom-up" postorder traversal.

if (node == NULL)

return;

printPostorder(node->left); // First recur on left subtree


printPostorder(node->right); // Then recur on right subtree

printf("%d ", node->data); // Now deal with the node

int main() // Driver code

struct node* root = newNode(1);

root->left = newNode(2);

root->right = newNode(3);

root->left->left = newNode(4);

root->left->right = newNode(5);

printf("Post order traversal of binary tree is \n"); // Function call

printPostorder(root);

getchar();

return 0;

Output:
Post order traversal of binary tree is
4 5 2 3 1
Example:2

#include<stdio.h>

#include<stdlib.h>

struct node

{
int key;

struct node *left;

struct node *right;

};

struct node *getNode(int val) //return a new node with the given value

struct node *newNode;

newNode = malloc (sizeof(struct node));

newNode->key = val;

newNode->left = NULL;

newNode->right = NULL;

return newNode;

//inserts nodes in the binary search tree

struct node *insertNode(struct node *root, int val)

if(root == NULL)

return getNode(val);

if(root->key < val)

root->right = insertNode(root->right, val);

if(root->key > val)

root->left = insertNode(root->left, val);


return root;

void postorder(struct node *root) //postorder traversal of the binary search


tree

if(root == NULL)

return;

postorder(root->left); //traverse the left subtree

postorder(root->right); //traverse the right subtree

printf("%d ",root->key); //visit the root

int main()

struct node *root = NULL;

int data;

char ch;

/* Do while loop to display various options to select from to decide the input */

do

printf("\n Select one of the operations::");

printf("\n1. To insert a new node in the Binary Tree");


printf("\n2. To display the nodes of the Binary Tree(via Postorder
Traversal).\n");

int choice;

scanf("%d", &choice);

switch (choice)

case1:

printf("\n Enter the value to be inserted\n");

scanf("%d", &data);

root = insertNode(root, data);

break;

case2:

printf("\n Post order Traversal of the Binary Tree::\n");

postorder(root);

break;

default:

printf("Wrong Entry\n");

break;

printf("\n Do you want to continue (Type y or n)\n");

scanf(" %c", &ch);

}
while (ch == 'Y'|| ch == 'y');

return 0;

Output:

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Postorder Traversal).

Enter the value to be inserted

10

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Postorder Traversal).

Enter the value to be inserted

30

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree


2. To display the nodes of the Binary Tree(via Postorder Traversal).

Enter the value to be inserted

20

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Postorder Traversal).

Enter the value to be inserted

50

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Postorder Traversal).

Enter the value to be inserted

60

Do you want to continue (Type y or n)

y
Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Postorder Traversal).

Enter the value to be inserted

55

Do you want to continue (Type y or n)

Select one of the operations::

1. To insert a new node in the Binary Tree

2. To display the nodes of the Binary Tree(via Postorder Traversal).

Postorder Traversal of the Binary Tree::

20 55 60 50 30 10

Do you want to continue (Type y or n)


Tree implementation Example:6
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode // Define the structure for tree nodes
{
int data;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;

TreeNode* createNode(int data) // create New node


{
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}

TreeNode* insertNode(TreeNode* root, int data) //Insert a Node into the Tree
{
if (root == NULL) // If the tree is empty, return a new node
{
return createNode(data);
}
if (data < root->data) // Otherwise, recur down the tree
{
root->left = insertNode(root->left, data);
}
else
{
root->right = insertNode(root->right, data);
}
return root;
}

void inorderTraversal(TreeNode* root) //Traverse the Tree - In-order traversal


{
if (root != NULL)
{
inorderTraversal(root->left);
printf("%d ", root->data);
inorderTraversal(root->right);
}
}

void deleteTree(TreeNode* root) // Function to delete the entire tree


{
if (root != NULL)
{
deleteTree(root->left);
deleteTree(root->right);
free(root);
}
}

int main()
{
TreeNode* root = NULL;
root = insertNode(root, 50); // Insert nodes into the tree
insertNode(root, 30);
insertNode(root, 20);
insertNode(root, 40);
insertNode(root, 70);
insertNode(root, 60);
insertNode(root, 80);
printf("In-order traversal:\n "); // Print the in-order traversal of the tree
inorderTraversal(root);
printf("\n");
deleteTree(root); // Delete the entire tree
return 0;
}
Output:
In-order traversal:
20 30 40 50 60 70 80
Binary Search Tree Example:7
#include <stdio.h>
#include <stdlib.h>
typedef struct Node // Define the structure for a node in the binary search tree
{
int value;
struct Node *left;
struct Node *right;
} Node;

Node* createNode(int value) // Function to create a new node


{
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->value = value;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}

Node* insert(Node* root, int value) // Function to insert a value into the BST
{
if (root == NULL) // If the tree is empty, return a new node
{
return createNode(value);
}
if (value < root->value) // Otherwise, recur down the tree
{
root->left = insert(root->left, value);
}
else if (value > root->value)
{
root->right = insert(root->right, value);
}
return root; // Return the (unchanged) node pointer
}

void inorderTraversal(Node* root) // Function to perform an in-order traversal of the BST


{
if (root != NULL)
{
inorderTraversal(root->left);
printf("%d ", root->value);
inorderTraversal(root->right);
}
}

void freeTree(Node* root) // Function to free the allocated memory of the BST
{
if (root != NULL)
{
freeTree(root->left);
freeTree(root->right);
free(root);
}
}
int main()
{
Node* root = NULL;
root = insert(root, 50); // Insert values into the BST
insert(root, 30);
insert(root, 70);
insert(root, 20);
insert(root, 40);
insert(root, 60);
insert(root, 80);
printf("In-order traversal: "); // Perform in-order traversal
inorderTraversal(root);
printf("\n");
freeTree(root); // Free allocated memory
return 0;
}
Output:
In-order traversal:
20 30 40 50 60 70 80
Example:8
Binary Search Tree (in-Order, Pre-Order and Post-Order-)
#include <stdio.h>
#include <stdlib.h>
typedef struct Node // Define the structure for a node in the BST
{
int data;
struct Node* left;
struct Node* right;
} Node;

Node* createNode(int data) // Function to create a new node


{
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode)
{
printf("Memory error\n");
return NULL;
}
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
Node* insertNode(Node* root, int data) // Function to insert a new node into the BST
{
if (root == NULL)
{
return createNode(data); // If the tree is empty, create the root node
}
if (data < root->data)
{
root->left = insertNode(root->left, data); // Insert into the left subtree
}
else
{
root->right = insertNode(root->right, data); // Insert into the right subtree
}
return root;
}

void inOrderTraversal(Node* root) // Function for in-order traversal


{
if (root != NULL)
{
inOrderTraversal(root->left);
printf("%d ", root->data);
inOrderTraversal(root->right);
}
}
void preOrderTraversal(Node* root) // Function for pre-order traversal
{
if (root != NULL)
{
printf("%d ", root->data);
preOrderTraversal(root->left);
preOrderTraversal(root->right);
}
}

void postOrderTraversal(Node* root) // Function for post-order traversal


{
if (root != NULL)
{
postOrderTraversal(root->left);
postOrderTraversal(root->right);
printf("%d ", root->data);
}
}

void freeTree(Node* root) // Function to free the memory allocated for the BST
{
if (root != NULL)
{
freeTree(root->left);
freeTree(root->right);
free(root);
}
}
int main()
{
Node* root = NULL;
root = insertNode(root, 50); // Insert nodes into the BST
insertNode(root, 30);
insertNode(root, 70);
insertNode(root, 20);
insertNode(root, 40);
insertNode(root, 60);
insertNode(root, 80);
printf("In-order traversal: "); // Perform in-order traversal
inOrderTraversal(root);
printf("\n");
printf("Pre-order traversal: "); // Perform pre-order traversal
preOrderTraversal(root);
printf("\n");
printf("Post-order traversal: "); // Perform post-order traversal
postOrderTraversal(root);
printf("\n");
freeTree(root); // Free allocated memory
return 0;
}
Output:
In-order traversal: 20 30 40 50 60 70 80
Pre-order traversal: 50 30 20 40 70 60 80
Post-order traversal: 20 40 30 60 80 70 50
Example:9
Binary search Tree Operations (Insertion, Deletion, Traverse and Search)
#include <stdio.h>
#include <stdlib.h>
typedef struct Node // Define the node structure
{
int data;
struct Node* left;
struct Node* right;
} Node;

Node* createNode(int data) // Create a new node


{
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
Node* insert(Node* root, int data)
{
if (root == NULL)
{
return createNode(data);
}
if (data < root->data)
{
root->left = insert(root->left, data);
}
else if (data > root->data)
{
root->right = insert(root->right, data);
}
return root;
}

Node* search(Node* root, int key)


{
if (root == NULL || root->data == key)
{
return root;
}
if (root->data > key)
{
return search(root->left, key);
}
return search(root->right, key);
}
void inorderTraversal(Node* root)
{
if (root != NULL)
{
inorderTraversal(root->left);
printf("%d ", root->data);
inorderTraversal(root->right);
}
}
Node* findMin(Node* root)
{
while (root->left != NULL)
{
root = root->left;
}
return root;
}
Node* deleteNode(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
{
if (root->left == NULL) // Node with only one child or no child
{
Node* temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL)
{
Node* temp = root->left;
free(root);
return temp;
}
Node* temp = findMin(root->right); // Node with two children
root->data = temp->data;
root->right = deleteNode(root->right, temp->data);
}
return root;
}
int main()
{
Node* root = NULL;
root = insert(root, 50);
root = insert(root, 30);
root = insert(root, 70);
root = insert(root, 20);
root = insert(root, 40);
root = insert(root, 60);
root = insert(root, 80);
printf("Inorder traversal: ");
inorderTraversal(root);
printf("\n");
printf("Deleting 20\n");
root = deleteNode(root, 20);
printf("Inorder traversal: ");
inorderTraversal(root);
printf("\n");
printf("Deleting 30\n");
root = deleteNode(root, 30);
printf("Inorder traversal: ");
inorderTraversal(root);
printf("\n");
printf("Deleting 50\n");
root = deleteNode(root, 50);
printf("Inorder traversal: ");
inorderTraversal(root);
printf("\n");
Node* searchResult = search(root, 70);
if (searchResult != NULL)
{
printf("Found 70 in the tree.\n");
}
else
{
printf("70 not found in the tree.\n");
}
return 0;
}

Output:
Inorder traversal: 20 30 40 50 60 70 80
Deleting: 20
Inorder traversal: 30 40 50 60 70 80
Deleting: 30
Inorder traversal: 40 50 60 70 80
Deleting: 50
Inorder traversal: 40 60 70 80
Found 70 in the tree.
Example: (Practice Program) Threaded Binary Tree

#include <stdio.h>

#include <stdlib.h>

typedef enum {false,true} boolean;

struct node *in_succ(struct node *p);

struct node *in_pred(struct node *p);

struct node *insert(struct node *root, int ikey);

struct node *del(struct node *root, int dkey);

struct node *case_a(struct node *root, struct node *par,struct node *ptr);

struct node *case_b(struct node *root,struct node *par,struct node *ptr);

struct node *case_c(struct node *root, struct node *par,struct node *ptr);

void inorder( struct node *root);

void preorder( struct node *root);

struct node

struct node *left;

boolean lthread;

int info;

boolean rthread;

struct node *right;

};

int main( )
{

int choice,num;

struct node *root=NULL;

while(1)

printf("\Program of Threaded Tree in C\n");

printf("1.Insert\n");

printf("2.Delete\n");

printf("3.Inorder Traversal\n");

printf("4.Preorder Traversal\n");

printf("5.Quit\n");

printf("\nEnter your choice : ");

scanf("%d",&choice);

switch(choice)

case 1:

printf("\nEnter the number to be inserted : ");

scanf("%d",&num);

root = insert(root,num);

break;

case 2:

printf("\nEnter the number to be deleted : ");


scanf("%d",&num);

root = del(root,num);

break;

case 3:

inorder(root);

break;

case 4:

preorder(root);

break;

case 5:

exit(1);

default:

printf("\nWrong choice\n");

return 0;

struct node *insert(struct node *root, int ikey)

struct node *tmp,*par,*ptr;

int found=0;

ptr = root;
par = NULL;

while( ptr!=NULL )

if( ikey == ptr->info)

found =1;

break;

par = ptr;

if(ikey < ptr->info)

if(ptr->lthread == false)

ptr = ptr->left;

else

break;

else

if(ptr->rthread == false)

ptr = ptr->right;

else

break;
}

if(found)

printf("\nDuplicate key");

else

tmp=(struct node *)malloc(sizeof(struct node));

tmp->info=ikey;

tmp->lthread = true;

tmp->rthread = true;

if(par==NULL)

root=tmp;

tmp->left=NULL;

tmp->right=NULL;

else if( ikey < par->info )

tmp->left=par->left;

tmp->right=par;

par->lthread=false;

par->left=tmp;
}

else

tmp->left=par;

tmp->right=par->right;

par->rthread=false;

par->right=tmp;

return root;

struct node *del(struct node *root, int dkey)

struct node *par,*ptr;

int found=0;

ptr = root;

par = NULL;

while( ptr!=NULL)

if( dkey == ptr->info)

found =1;
break;

par = ptr;

if(dkey < ptr->info)

if(ptr->lthread == false)

ptr = ptr->left;

else

break;

else

if(ptr->rthread == false)

ptr = ptr->right;

else

break;

if(found==0)

printf("\ndkey not present in tree");

else if(ptr->lthread==false && ptr->rthread==false)/*2 children*/

root = case_c(root,par,ptr);
else if(ptr->lthread==false )

root = case_b(root, par,ptr);

else if(ptr->rthread==false)

root = case_b(root, par,ptr);

else

root = case_a(root,par,ptr);

return root;

struct node *case_a(struct node *root, struct node *par,struct node *ptr )

if(par==NULL)

root=NULL;

else if(ptr==par->left)

par->lthread=true;

par->left=ptr->left;

else

par->rthread=true;

par->right=ptr->right;

}
free(ptr);

return root;

struct node *case_b(struct node *root,struct node *par,struct node *ptr)

struct node *child,*s,*p;

if(ptr->lthread==false)

child=ptr->left;

else

child=ptr->right;

if(par==NULL )

root=child;

else if( ptr==par->left)

par->left=child;

else

par->right=child;

s=in_succ(ptr);

p=in_pred(ptr);

if(ptr->lthread==false)

p->right=s;

else

{
if(ptr->rthread==false)

s->left=p;

free(ptr);

return root;

struct node *case_c(struct node *root, struct node *par,struct node *ptr)

struct node *succ,*parsucc;

parsucc = ptr;

succ = ptr->right;

while(succ->left!=NULL)

parsucc = succ;

succ = succ->left;

ptr->info = succ->info;

if(succ->lthread==true && succ->rthread==true)

root = case_a(root, parsucc,succ);

else

root = case_b(root, parsucc,succ);

return root;
}

struct node *in_succ(struct node *ptr)

if(ptr->rthread==true)

return ptr->right;

else

ptr=ptr->right;

while(ptr->lthread==false)

ptr=ptr->left;

return ptr;

struct node *in_pred(struct node *ptr)

if(ptr->lthread==true)

return ptr->left;

else

ptr=ptr->left;

while(ptr->rthread==false)

ptr=ptr->right;
return ptr;

void inorder( struct node *root)

struct node *ptr;

if(root == NULL )

printf("Tree is empty");

return;

ptr=root;

while(ptr->lthread==false)

ptr=ptr->left;

while( ptr!=NULL )

printf("%d ",ptr->info);

ptr=in_succ(ptr);

void preorder(struct node *root )

{
struct node *ptr;

if(root==NULL)

printf("Tree is empty");

return;

ptr=root;

while(ptr!=NULL)

printf("%d ",ptr->info);

if(ptr->lthread==false)

ptr=ptr->left;

else if(ptr->rthread==false)

ptr=ptr->right;

else

while(ptr!=NULL && ptr->rthread==true)

ptr=ptr->right;

if(ptr!=NULL)

ptr=ptr->right;

}
}

Output:

Program of Threaded Tree:

1.Insert

2.Delete

3.Inorder Traversal

4.Preorder Traversal

5.Quit

Enter your choice : 1

Enter the number to be inserted : 10

Program of Threaded Tree:

1.Insert

2.Delete

3.Inorder Traversal

4.Preorder Traversal

5.Quit

Enter your choice : 1

Enter the number to be inserted : 30

Program of Threaded Tree:

1.Insert

2.Delete

3.Inorder Traversal
4.Preorder Traversal

5.Quit

Enter your choice : 1

Enter the number to be inserted : 50

Program of Threaded Tree:

1.Insert

2.Delete

3.Inorder Traversal

4.Preorder Traversal

5.Quit

Enter your choice : 1

Enter the number to be inserted : 20

Program of Threaded Tree:

1.Insert

2.Delete

3.Inorder Traversal

4.Preorder Traversal

5.Quit

Enter your choice : 1

Enter the number to be inserted : 80

Program of Threaded Tree:

1.Insert
2.Delete

3.Inorder Traversal

4.Preorder Traversal

5.Quit

Enter your choice : 1

Enter the number to be inserted : 70

Program of Threaded Tree:

1.Insert

2.Delete

3.Inorder Traversal

4.Preorder Traversal

5.Quit

Enter your choice : 3

10 20 30 50 70 80

Program of Threaded Tree:

1.Insert

2.Delete

3.Inorder Traversal

4.Preorder Traversal

5.Quit

Enter your choice :


Out off Syllabus)

Types of Trees

1. General tree
2. Binary tree
3. Binary Search Tree
4. AVL Tree
5. B Tree
6. Red Black Tree
7. Expression Tree
8. Tournament Tree
9. Forest Tree
10.Splay tree
General tree:

The general tree is one of the types of tree data structure.


In the general tree, a node can have either 0 or maximum n number of
nodes.
There is no restriction imposed on the degree of the node (the number of
nodes that a node can contain).
The topmost node in a general tree is known as a root node. The children
of the parent node are known as subtrees.

Binary Tree:
A Binary Tree is a type of tree data structure where each node can
have a maximum of two child nodes, a left child node and a right child node.

This restriction, that a node can have a maximum of two child nodes,

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.

Binary Search Tree:


Binary search tree is a non-linear data structure in which one node is
connected to n number of nodes.
It is a node-based data structure.
A node can be represented in a binary search tree with three fields, i.e.,
data part, left-child, and right-child.
A node can be connected to the utmost two child nodes in a binary
search tree.
So, the node contains two pointers (left child and right child pointer).
Every node in the left subtree must contain a value less than the value of
the root node, and the value of each node in the right subtree must be
bigger than the value of the root node.
Forest Tree:
A forest is an undirected graph in which any two vertices are
connected by at most one path. Equivalently, a forest is an undirected acyclic
graph, all of whose connected components are trees; in other words, the graph
consists of a disjoint union of trees.
AVL Tree:
AVL tree is a self-balancing Binary Search Tree (BST) where the
difference between heights of left and right subtrees for any node cannot be
more than one.
AVL tree satisfies the property of the binary tree as well as of the binary search
tree.

B Tree:
B-tree is a self-balancing tree data structure that maintains sorted data
and allows searches, sequential access, insertions, and deletions in logarithmic
time. The B-tree generalizes the binary search tree, allowing for nodes with
more than two children.
Red Black Tree:

A red-black tree is a binary search tree which has the


following red-black properties: Every node is either red or black. Every leaf
(NULL) is black. If a node is red, then both its children are black. Every simple
path from a node to a descendant leaf contains the same number of black nodes.

Case 1: Check whether the tree is empty; make the current node as the root and

color the node black if it is empty.

Case 2: But if the tree is not empty, we create a new node and colour it red.

You might also like