0% found this document useful (0 votes)
12 views18 pages

Data Structures - Trees Notes

Uploaded by

rajamahesh
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
12 views18 pages

Data Structures - Trees Notes

Uploaded by

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

Trees

Binary Trees: The tree in C is a non-linear data structure, i.e. The elements are not stored
sequentially, and in the tree in C, they are present in levels.
i. A binary tree in C is a data structure in which every node can have a maximum of
two children nodes.
ii. Children nodes are labeled as right and left child. Each node in the binary tree
contains a value and two pointers pointing to the children.
iii. The topmost node of the binary tree is called the root node and the bottom-most
nodes of the binary tree are called leaf nodes.
iv. The height of a binary tree is calculated by taking the longest path between the
root and the leaf node.

Tree Terminologies:-
1. Root:- A root is a node without a parent.
2. Siblings:- Siblings mean that nodes which have the same parent node.
3. Internal Node:- Internal Node means that a node which has at least a single child.
4. External Node:- External Node means that a node which has no children. It is also
known as leaf.
5. Ancestors:- Ancestors include the parent, grandparent and so on of a node.
6. Descendants:- Descendants are the opposite of ancestors, It includes the child,
grandchild and so on of a node.
7. Edge:- An edge means a connection between one node to another node.
8. Path:- Path is a combination of nodes and edges connected with each other.
There are four types of Binary tree:

o Full/ proper/ strict Binary tree


o Complete Binary tree
o Perfect Binary tree
o Degenerate Binary tree
o Skewed Binary Tree
o Balanced Binary tree

o Full/ proper/ strict Binary tree

The full binary tree is also known as a strict binary tree. The tree can only be considered as
the full binary tree if each node must contain either 0 or 2 children. The full binary tree can
also be defined as the tree in which each node must contain 2 children except the leaf nodes.

o Complete Binary Tree

The complete binary tree is a tree in which all the nodes are completely filled except the last
level. In the last level, all the nodes must be as left as possible. In a complete binary tree, the
nodes should be added from the left.
o Perfect Binary Tree

A tree is a perfect binary tree if all the internal nodes have 2 children, and all the leaf nodes
are at the same level.

o Degenerate Binary Tree

The degenerate binary tree is a tree in which all the internal nodes have only one children.

o Skewed Binary Tree

A skewed binary tree is a pathological/degenerate tree in which the tree is either dominated
by the left nodes or the right nodes. Thus, there are two types of skewed binary tree: left-
skewed binary tree and right-skewed binary tree.
o Balanced Binary Tree

It is a type of binary tree in which the difference between the height of the left and the
right subtree for each node is either 0 or 1.

Representation of Binary Tree:

A Binary tree is implemented with the help of pointers. The first node in the tree is
represented by the root pointer. Each node in the tree consists of three parts, i.e.,
o Data
o left pointer and
o right pointer.
To create a binary tree, we first need to create the node.
In C, we can represent a tree node using structures. In other languages, we can use classes as
part of their OOP feature. Below is an example of a tree node with integer data.
// Structure of each node of the tree
struct node {
int data;
struct node* left;
struct node* right;
};

Basic Operations On Binary Tree:


• Inserting an element.
• Removing an element.
• Searching for an element.
• Deletion for an element.
• Traversing an element. There are four (mainly three) types of traversals in a
binary tree which will be discussed ahead.

Binary Tree Traversals:


Tree Traversal algorithms can be classified broadly into two categories:
• Depth-First Search (DFS) Algorithms
• Breadth-First Search (BFS) Algorithms

Tree Traversal using Depth-First Search (DFS) algorithm can be further classified into
three categories:

• Preorder Traversal (current-left-right): Visit the current node before visiting


any nodes inside the left or right subtrees. Here, the traversal is root – left child
– right child. It means that the root node is traversed first then its left child and
finally the right child.
• Inorder Traversal (left-current-right): Visit the current node after visiting all
nodes inside the left subtree but before visiting any node within the right
subtree. Here, the traversal is left child – root – right child. It means that the
left child is traversed first then its root node and finally the right child.
• Postorder Traversal (left-right-current): Visit the current node after visiting all
the nodes of the left and right subtrees. Here, the traversal is left child – right
child – root. It means that the left child has traversed first then the right child
and finally its root node.
Now, let us write the traversal sequences for this binary search tree-

Preorder Traversal-
100 , 20 , 10 , 30 , 200 , 150 , 300

Inorder Traversal-
10 , 20 , 30 , 100 , 150 , 200 , 300

Postorder Traversal-
10 , 30 , 20 , 150 , 300 , 200 , 100

Tree Traversal using Breadth-First Search (BFS) algorithm can be further classified into
one category:

• Level Order Traversal: Visit nodes level-by-level and left-to-right fashion at the
same level. Here, the traversal is level-wise. It means that the most left child
has traversed first and then the other children of the same level from left to
right have traversed.

Let us traverse the following tree with all four traversal methods:
Binary Tree

Pre-order Traversal of the above tree: 1-2-4-5-3-6-7


In-order Traversal of the above tree: 4-2-5-1-6-3-7
Post-order Traversal of the above tree: 4-5-2-6-7-3-1
Level-order Traversal of the above tree: 1-2-3-4-5-6-7

Example:
// Tree traversal in C
#include <stdio.h>
#include <stdlib.h>
struct node {
int item;
struct node* left;
struct node* right;
};

// Inorder traversal
void inorderTraversal(struct node* root) {
if (root == NULL) return;
inorderTraversal(root->left);
printf("%d ->", root->item);
inorderTraversal(root->right);
}
// Preorder traversal
void preorderTraversal(struct node* root) {
if (root == NULL) return;
printf("%d ->", root->item);
preorderTraversal(root->left);
preorderTraversal(root->right);
}

// Postorder traversal
void postorderTraversal(struct node* root) {
if (root == NULL) return;
postorderTraversal(root->left);
postorderTraversal(root->right);
printf("%d ->", root->item);
}

// Create a new Node


struct node* createNode(value) {
struct node* newNode = malloc(sizeof(struct node));
newNode->item = value;
newNode->left = NULL;
newNode->right = NULL;

return newNode;
}

// Insert on the left of the node


struct node* insertLeft(struct node* root, int value) {
root->left = createNode(value);
return root->left;
}

// Insert on the right of the node


struct node* insertRight(struct node* root, int value) {
root->right = createNode(value);
return root->right;
}

int main() {
struct node* root = createNode(1);
insertLeft(root, 2);
insertRight(root, 3);
insertLeft(root->left, 4);
printf("Inorder traversal \n");
inorderTraversal(root);
printf("\nPreorder traversal \n");
preorderTraversal(root);
printf("\nPostorder traversal \n");
postorderTraversal(root);
}

Search Trees:
A tree is a kind of data structure that is used to represent the data in hierarchical form. It can
be defined as a collection of objects or entities called as nodes that are linked together to
simulate a hierarchy. Tree is a non-linear data structure as the data in a tree is not stored
linearly or sequentially.

Binary Search Tree:


A binary search tree is a tree data structure that allows the user to store elements in a sorted
manner. It is called a binary tree because each node can have a maximum of two children and
is called a search tree.
i. A binary Search Tree is a special tree in which some order is followed.
ii. Every parent node has at most two children in which the left children have a lesser value
while the right children have a higher value than their parent.
iii. This rule is applied to all left and right subtrees.

Advantages of Binary search tree

o Searching an element in the Binary search tree is easy as we always have a hint that
which subtree has the desired element.
o As compared to array and linked lists, insertion and deletion operations are faster in
BST.

• Search Operation

In Search, we have to find a specific element in the data structure. This searching operation
becomes simpler in binary search trees because here elements are stored in sorted order.
The steps of searching a node in Binary Search tree are listed as follows -

1. First, compare the element to be searched with the root element of the tree.
2. If root is matched with the target element, then return the node's location.
3. If it is not matched, then check whether the item is less than the root element, if it is
smaller than the root element, then move to the left subtree.
4. If it is larger than the root element, then move to the right subtree.
5. Repeat the above procedure recursively until the match is found.
6. If the element is not found or not present in the tree, then return NULL.

Step 1:

Step2:

Step3:
• 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 -

o The node to be deleted is the leaf node, or,


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

We will understand the situations listed above in detail.

When the node to be deleted is the leaf node

It is the simplest case to delete a node in BST. Here, we have to replace the leaf node with
NULL and simply free the allocated space.

We can see the process to delete a leaf node from BST in the below image. In below image,
suppose we have to 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.

When the node to be deleted has only one child


In this case, we have to replace the target node with its child, and then delete the child node.
It means that after replacing the target node with its child node, the child node will now
contain the value to be deleted. So, we simply have to replace the child node with NULL and
free up the allocated space.

We can see the process of deleting a node with one child from BST in the below image. In the
below image, suppose we have to delete the node 79, as the node to be deleted has only one
child, so it will be replaced with its child 55.

So, the replaced node 79 will now be a leaf node that can be easily deleted.

When the node to be deleted has two children

This case of deleting a node in BST is a bit complex among other two cases. In such a case, the
steps to be followed are listed as follows -

o First, find the inorder successor of the node to be deleted.


o After that, replace that node with the inorder successor until the target node is placed
at the leaf of tree.
o And at last, replace the node with NULL and free up the allocated space.

The inorder successor is required when the right child of the node is not empty. We can obtain
the inorder successor by finding the minimum element in the right child of the node.

We can see the process of deleting a node with two children from BST in the below image. In
the below image, suppose we have to delete node 45 that is the root node, as the node to be
deleted has two children, so it will be replaced with its inorder successor. Now, node 45 will
be at the leaf of the tree so that it can be deleted easily.
Now let's understand how insertion is performed on a binary search tree.

• Insertion in Binary Search tree

A new key in BST is always inserted at the leaf. To insert an element in BST, we have to start
searching from the root node; if the node to be inserted is less than the root node, then search
for an empty location in the left subtree. Else, search for the empty location in the right
subtree and insert the data. Insert in BST is similar to searching, as we always have to maintain
the rule that the left subtree is smaller than the root, and right subtree is larger than the root.

Now, let's see the process of inserting a node into BST using an example.
Example Program:
// Binary Search Tree operations in C

#include <stdio.h>
#include <stdlib.h>

struct node {
int key;
struct node *left, *right;
};

// Create a node
struct node *newNode(int item) {
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}

// Inorder Traversal
void inorder(struct node *root) {
if (root != NULL) {
// Traverse left
inorder(root->left);

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

// Traverse right
inorder(root->right);
}
}

// Insert a node
struct node *insert(struct node *node, int key) {
// Return a new node if the tree is empty
if (node == NULL) return newNode(key);

// Traverse to the right place and insert the node


if (key < node->key)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
return node;
}

// Find the inorder successor


struct node *minValueNode(struct node *node) {
struct node *current = node;

// Find the leftmost leaf


while (current && current->left != NULL)
current = current->left;
return current;
}

// Deleting a node
struct node *deleteNode(struct node *root, int key) {
// Return if the tree is empty
if (root == NULL) return root;

// Find the node to be deleted


if (key < root->key)
root->left = deleteNode(root->left, key);
else if (key > root->key)
root->right = deleteNode(root->right, key);

else {
// If the node is with only one child or no child
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;
}

// If the node has two children


struct node *temp = minValueNode(root->right);

// Place the inorder successor in position of the node to be deleted


root->key = temp->key;

// Delete the inorder successor


root->right = deleteNode(root->right, temp->key);
}
return root;
}

// Driver code
int main() {
struct node *root = NULL;
root = insert(root, 8);
root = insert(root, 3);
root = insert(root, 1);
root = insert(root, 6);
root = insert(root, 7);
root = insert(root, 10);
root = insert(root, 14);
root = insert(root, 4);

printf("Inorder traversal: ");


inorder(root);

printf("\nAfter deleting 10\n");


root = deleteNode(root, 10);
printf("Inorder traversal: ");
inorder(root);
}

You might also like