Unit 5
Unit 5
Trees: Introduction, Binary Trees, Binary Tree Traversals, Heaps, Binary Search trees
(BST): Definition, Searching an element, Insertion into a BST, Deletion from a BST.
Efficient Binary Search Trees: AVL Trees: Definition, Searching an element Insertion into an
AVL
==========================================================================
A tree is a hierarchical data structure.
It consists of nodes connected by edges and is often used to represent data with a
parent-child relationship.
Tree Terminology
1. Root: The top node in the tree. Every tree has a single root node.
2. Edges: The connections between nodes.
3. Child: A node directly connected to another node when moving away from the root.
4. Parent: A node connected to another node closer to the root.
5. Leaf: A node with no children.
6. Subtree: A tree consisting of a node and its descendants.
7. Height: The length of the longest path from the root.
8. Depth: The length of the path from the root to a node.
9. Strict Binary Tree: Every node has 0 or 2 children.
10. Complete Binary Tree. All levels are completely filled except last level.
Types of Trees
1. General Tree: A tree with no specific constraints on the number of children.
2. Binary Tree: Each node has at most two children left and right.
3. Binary Search Tree (BST): A binary tree where the left child contains values less than
the parent and the right child contains values greater than the parent.
4. Balanced Tree: A tree where the height difference between left and right subtrees is
one. Example AVL Tree, Red-Black Tree.
5. Heap: A binary tree that satisfies the heap property min-heap or max-heap.
6. B Trees
7. B+ Trees
Common Operations
Traversal:
DSA_UNIT_4 MRS.MADHAVI A
Preorder (NLR): Node → Left → Right
Inorder (LRR): Left → Node → Right
Postorder (LRR): Left → Right → Node
Level-order (BFS): Breadth-First Search
Insertion: Adding a new node.
Deletion: Removing a node while maintaining the structure.
Search: Finding a node with a specific value.
Applications
File systems
Network routing
Parsing expressions (Abstract Syntax Trees)
Databases (e.g., B-trees)
Artificial intelligence (decision trees)
struct Node
{
struct Node *left;
int data;
struct Node *right;
};
queue[rear++] = root;
return root;
}
int main()
{
struct Node *root = NULL, *copy = NULL, *mirror = NULL;
int choice, key;
DSA_UNIT_4 MRS.MADHAVI A
while (1)
{
printf("\nMenu:\n");
printf("1. Build Tree\n");
printf("2. Display Pre-order\n");
printf("3. Search Element using Level-order\n");
printf("4. Copy Tree and Display\n");
printf("5. Mirror Tree and Display\n");
printf("6. Delete Tree\n");
printf("7. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
if (root != NULL)
printf("Tree already exists. Please delete it first.\n");
else
{
printf("Building binary tree:\n");
root = buildTree();
printf("Tree built successfully.\n");
}
break;
case 2:
if (root)
{
printf("Pre-order display:\n");
displayTree(root);
printf("\n");
}
else
printf("Tree is empty. Build a tree first.\n");
break;
case 3:
if (root)
{
printf("Enter element to search: ");
scanf("%d", &key);
if (levelOrderSearch(root, key))
printf("%d found in the tree.\n", key);
else
printf("%d not found in the tree.\n", key);
DSA_UNIT_4 MRS.MADHAVI A
}
else
printf("Tree is empty. Build a tree first.\n");
break;
case 4:
if (root)
{
copy = copyTree(root);
printf("Copy is done. Pre-order traversal:\n");
displayTree(copy);
printf("\n");
}
else
printf("Tree is empty. Build a tree first.\n");
break;
case 5:
if (root)
{
mirror = mirrorTree(root);
printf("Mirror image is done. Pre-order traversal:\n");
displayTree(mirror);
printf("\n");
}
else
printf("Tree is empty. Build a tree first.\n");
break;
case 6:
if (root)
{
deleteTree(root);
root = NULL;
printf("Original tree deleted successfully.\n");
}
else
printf("Tree is empty. Build a tree first.\n");
break;
case 7:
printf("Exited the program\n");
if (root) deleteTree(root);
if (copy) deleteTree(copy);
if (mirror) deleteTree(mirror);
exit(0);
break;
default:
printf("Invalid choice. Please try again.\n");
DSA_UNIT_4 MRS.MADHAVI A
}
}
return 0;
}
Binary Tree Traversals
Tree traversal is dealing with hierarchical data structures such as trees. Traversal means
visiting all the nodes of a tree systematically, ensuring that no node is missed. There are two
main types of tree traversal methods.
A Binary Search Tree (BST) is a special type of binary tree where each node has the following
properties.
1. Key property
The left subtree of a node contains only nodes with keys less than the
node’s key.
The right subtree of a node contains only nodes with keys greater than the
node’s key.
2. Structure
Each node has at most two children (binary tree property).
DSA_UNIT_4 MRS.MADHAVI A
Use Case: Preorder traversal is used to create a copy of the tree or to serialize it for
storage.
Postorder Traversal (Left, Right, Root)
1. Traverse the left subtree.
2. Traverse the right subtree.
3. Visit the root node.
Use Case: Postorder traversal is used for evaluating expressions, freeing memory, or
deleting nodes in a tree structure.
Breadth-First Traversal (BFS) or Level Order Traversal
Instead of exploring deep branches, BFS traverses the tree level by level. It visits all the nodes
at a particular depth before moving on to nodes at the next depth.
Level Order Traversal
1. Start from the root node.
2. Visit all the nodes at the current level (from left to right).
3. Move to the next level and repeat the process until all levels are traversed.
Use Case: BFS is particularly useful in shortest-path algorithms (e.g., in graphs),
finding nodes at a specific depth, or traversing trees with arbitrary branching.
Comparison of DFS and BFS
Aspect Depth-First Traversal (DFS) Breadth-First Traversal (BFS)
Order Follows a branch to its deepest node Visits nodes level by level.
before backtracking.
Space O(h) where h is the height of the tree O(w) where w is the maximum width
Complexity (stack-based). of the tree (queue-based).
Use Cases Useful for recursive problems, tree copy, Useful for recursive problems, tree
and expression evaluation. copy, and expression evaluation.
struct Node
{
struct Node *left;
int data;
struct Node *right;
};
DSA_UNIT_4 MRS.MADHAVI A
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;
}
int main()
{
printf("Build a binary tree\n");
struct Node* root = buildTree();
return 0;
}
Heap Data Structures
Heap is a specialized tree-based data structure that satisfies the heap property. The heap
property is a condition that must be maintained for every node in the heap. There are two
common types of heaps: the max heap and the min heap.
Applications of heaps: Task scheduling, graph algorithms and dynamic memory allocation.
Max Heap
In a max heap, for every node 'i', the value of 'i' is less than or equal to the value of its parent.
In other words, the value of each node is greater than or equal to the values of its children
except root node since the root node does have parent.
DSA_UNIT_4 MRS.MADHAVI A
The process of building a max heap from an array is called heapify. You start from the
last non-leaf node and move upwards, applying heapify operation at each step. This
ensures that the heap property is satisfied.
The time complexity of building a max heap from an array of size n is O(n).
To insert an element into a max heap, adding a new element at the end of the heap
and then perform a heapify operation to restore the heap property.
Algorithm
function heapifyUp(heap, index):
while index > 0 && heap[parent(index)] < heap[index]:
swap(heap[parent(index)], heap[index])
index = parent(index)
Suppose the Heap is a Max-Heap as
10
/ \
5 3
/ \
2 4
The new element to be inserted is 15.
Step 1: Insert the new element at the end.
10
/ \
5 3
/ \ /
2 4 15
Step 2: Heapify the new element following bottom-up approach.
since15 is greater than its parent 3, swap them.
10
/ \
5 15
/ \ /
2 4 3
15 is again more than its parent 10, swap them.
15
/ \
5 10
/ \ /
2 4 3
DSA_UNIT_4 MRS.MADHAVI A
Therefore, the final heap after insertion is:
15
/ \
5 10
/ \ /
2 4 3
The time complexity of inserting an element into a max heap is O(log n), where n is the
number of elements in the heap.
To extract largest element from a heap, swap it with the last element, remove the last
element and then perform a heapify operation to maintain the heap property.
The time complexity of extracting the maximum element from a max heap is O(log n),
where n is the number of elements in the heap.
To sort an array using a max heap, build a max heap from the array and then
successively extract the maximum element until the heap is empty.
DSA_UNIT_4 MRS.MADHAVI A
Step 2: Heapify root. Final Heap:
5
/ \
4 3
/
2
Min Heap
A Minimum Priority Heap, a Min-Heap, is a type of binary heap data structure that maintains
the heap property. The heap property for a Min-Heap is defined as follows: for every node i
other than the root, the value of i is greater than or equal to the value of its parent.
Structure
A Min-Heap is typically implemented as a complete binary tree, where the values are stored
in such a way that the key of each node is less than or equal to the keys of its children.
The tree is usually represented as an array, where the root is at index 0 and for any element
at index i, its left child is at index 2*i + 1 and the right child is at index 2*i + 2.
Insertion Operation
When a new element is inserted into the Min-Heap, it is placed at the next available position
in the array.
The heap property may be violated after insertion, so a "happify-up" operation is performed
to restore the heap property. This involves swapping the new element with its parent until
the heap property is satisfied.
Deletion Operation
The minimum element in the Min-Heap is always at the root (index 0).
To remove the minimum element (extract-min), the last element in the array is moved to the
root, and a "happify-down" operation is performed to restore the heap property. This involves
swapping the root with its smallest child until the heap property is satisfied.
Time Complexity
The time complexity for insertion and deletion in a Min-Heap is O(log n), where n is the
number of elements in the heap.
This is because the height of a binary heap is logarithmic with respect to the number of
elements.
Applications
Min-Heaps are commonly used in priority queues, where the smallest element needs to be
efficiently accessed and removed.
Dijkstra's algorithm for finding the shortest path in a graph often uses Min-Heaps to
efficiently extract the minimum distance vertex.
DSA_UNIT_4 MRS.MADHAVI A
Heap Sort
Heap Sort is a comparison-based sorting algorithm that uses the properties of a binary heap
data structure. It sorts an array by first converting it into a heap and then repeatedly
extracting the largest or smallest element depending on the type of heap and rebuilding the
heap until the array is sorted.
DSA_UNIT_4 MRS.MADHAVI A
HEAP_SORT (arr):
1. BUILD_MAX_HEAP (arr)
2. for i = n-1 to 1:
SWAP (arr[0], arr[i])
MAX_HEAPIFY (arr, 0, i)
BUILD_MAX_HEAP (arr):
1. for i = floor(n/2) - 1 to 0:
MAX_HEAPIFY (arr, i, n)
Time Complexity
Building the Heap: O(n)
Heapify (per extraction): O (log n)
Extracting n elements: O (n log n)
Overall Time Complexity: O (n log n)
Space Complexity
In-place sorting: O(1) additional space.
No additional arrays or data structures are required.
DSA_UNIT_4 MRS.MADHAVI A
All the values in the right subtree of N are greater than the value of N.
2. This property applies recursively to every node in the tree.
Structure of a BST
A BST node typically contains:
1. A key or value.
2. A pointer to the left child (smaller values).
3. A pointer to the right child (larger values).
Operations on a BST
1. Searching
Goal: Find if a specific value exists in the BST.
Algorithm:
1. Compare the target value with the current node.
2. If the value equals the current node, return the node.
3. If the value is smaller, search in the left subtree.
4. If the value is larger, search in the right subtree.
Time Complexity: O(h), where h is the height of the tree. For a balanced tree, h = log(n).
2. Insertion
Goal: Add a new value to the BST while maintaining the binary search property.
Algorithm:
1. Start at the root node.
2. If the new value is smaller, recursively move to the left subtree.
3. If the new value is larger, recursively move to the right subtree.
4. When a null child is found, insert the new value there.
Time Complexity: O(h).
3. Deletion
Goal: Remove a node from the BST while maintaining the binary search property.
Cases:
1. Node has no children: Simply remove the node.
2. Node has one child: Replace the node with its child.
3. Node has two children:
DSA_UNIT_4 MRS.MADHAVI A
Find the inorder successor (smallest value in the right subtree) or the
inorder predecessor (largest value in the left subtree).
Replace the node's value with the successor/predecessor.
Delete the successor/predecessor node.
Time Complexity: O(h).
4. Traversals
BSTs support standard tree traversal methods:
Inorder Traversal: Produces a sorted order of elements.
Preorder and Postorder Traversals: Useful for specific tree-related algorithms.
Properties of a BST
1. Time Complexity:
o Best-case (Balanced tree): O(logn) for search, insert, and delete.
o Worst-case (Skewed tree): O(n).
2. Height:
o A perfectly balanced BST has a height of log (n), where n is the number of nodes.
3. Applications:
o Database indexing.
o Dynamic sets and ordered data.
o Searching and range queries.
Efficient search, insertion, and deletion Performance degrades if the tree becomes
(if balanced). skewed.
DSA_UNIT_4 MRS.MADHAVI A
Prog: WACP that implements Binary Search Tree by reading elements
from keyboard with insertion, deletion and search functions
#include <stdio.h>
#include <stdlib.h>
struct Node
{
struct Node* left;
int data;
struct Node* right;
};
DSA_UNIT_4 MRS.MADHAVI A
struct Node* search(struct Node* root, int data)
{
struct Node* current = root;
while (current != NULL && current->data != data)
{
if (data < current->data)
current = current->left;
else
current = current->right;
}
return current;
}
int main()
{
struct Node* root = NULL;
int choice, value;
while (1)
{
printf("\nBinary Search Tree Operations:\n");
printf("1. Insert\n");
printf("2. Delete\n");
printf("3. Search\n");
printf("4. Display Inorder\n");
printf("5. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
printf("Enter value to insert: ");
scanf("%d", &value);
root = insert(root, value);
break;
case 2:
printf("Enter value to delete: ");
scanf("%d", &value);
DSA_UNIT_4 MRS.MADHAVI A
root = deleteNode(root, value);
break;
case 3:
printf("Enter value to search: ");
scanf("%d", &value);
struct Node* result = search(root, value);
if (result != NULL)
printf("Value found: %d\n", result->data);
else
printf("Value not found.\n");
break;
case 4:
printf("Inorder Traversal: ");
inorderTraversal(root);
printf("\n");
break;
case 5:
printf("Exited the Program\n");
return 0;
default:
printf("Invalid choice\n");
}
}
return 0;
}
AVL Trees
An AVL tree is a type of self-balancing binary search tree (BST) A stands for Adelson – V
stands for Velsky and L stands for Landis. It maintains a balance condition to ensure efficient
operations by keeping the height of the tree minimal.
For any node in an AVL tree, the balance factor is defined as:
Balance Factor (BF) = Height of Left Subtree − Height of Right Subtree
The balance factor must be −1, 0, or1 for the tree to be balanced.
DSA_UNIT_4 MRS.MADHAVI A
3. Height-Balanced Tree:
The AVL tree ensures that the difference in height between the left and
right subtrees of any node is at most 1.
Operations in AVL Trees
1. Insertion
When inserting a new node, the AVL property balance factor might be violated.
After the insertion, if the tree becomes unbalanced, rotations are used to restore
balance.
Steps
1. Insert the new node as in a regular BST.
2. Update the heights of the affected nodes.
3. Check the balance factor:
If the balance factor is −2 or +2, the tree is unbalanced.
Perform rotations to rebalance the tree.
Rotations
1. LL - Problem: Perform a single right rotation.
2. RR - Problem: Perform a single left rotation.
3. LR - Problem: Perform a left rotation on the left child, followed by a right rotation on
the root.
4. RL - Problem: Perform a right rotation on the right child, followed by a left rotation on
the root.
2. Deletion
When deleting a node, the AVL property might again be violated.
Rotations are used to rebalance the tree after deletion.
Steps
1. Delete the node as in a regular BST.
2. Update the heights of the affected nodes.
3. Check the balance factor of each node and apply rotations if needed.
1. Left-Heavy (BF = +2):
If BF (left child) ≥ 0 perform a right rotation LL.
If BF (left child) < 0 perform a left-right rotation LR.
DSA_UNIT_4 MRS.MADHAVI A
2. Right-Heavy (BF = -2):
If BF (right child) ≤ 0, perform a left rotation (RR).
If BF (right child) > 0, perform a right-left rotation (RL).
Rotations
1. Right Rotation (LL Case):
Applicable when the left subtree is heavier due to a left child.
Procedure
1. Make the left child the new root.
2. Move the original root to the right subtree of the new root.
2. Left Rotation (RR Case):
Applicable when the right subtree is heavier due to a right child.
Procedure
1. Make the right child the new root.
2. Move the original root to the left subtree of the new root.
3. Left-Right Rotation (LR Case):
Applicable when the left subtree is heavier due to a right child.
Procedure
1. Perform a left rotation on the left child.
2. Perform a right rotation on the root.
4. Right-Left Rotation (RL Case):
Applicable when the right subtree is heavier due to a left child.
Procedure
1. Perform a right rotation on the right child.
2. Perform a left rotation on the root.
Time Complexity
Operation Average Case Worst Case
Search O (log n) O (log n)
Insert O (log n) O (log n)
Delete O (log n) O (log n)
DSA_UNIT_4 MRS.MADHAVI A
Advantages
1. Self-Balancing: Guarantees O (log n) height, ensuring efficient operations.
2. Search Efficiency: Particularly useful for datasets requiring frequent searching.
3. Well-Suited for Applications:
struct Node
{
int key;
struct Node *left, *right;
int height;
};
DSA_UNIT_4 MRS.MADHAVI A
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
node->key = key;
node->left = node->right = NULL;
node->height = 1;
return node;
}
int main()
{
struct Node *root = NULL;
int choice, key;
while (1)
{
printf("\n1. Insert\n2. Delete\n3. Display Inorder\n4. Exit\nEnter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
DSA_UNIT_4 MRS.MADHAVI A
printf("Enter key to insert: ");
scanf("%d", &key);
root = insert(root, key);
if (isAVL(root))
{
printf("Tree is AVL after inserting %d\n", key);
}
else
{
printf("Tree is NOT AVL after inserting %d\n", key);
}
break;
case 2:
printf("Enter key to delete: ");
scanf("%d", &key);
root = deleteNode(root, key);
if (isAVL(root))
{
printf("Tree is AVL after deleting %d\n", key);
}
else
{
printf("Tree is NOT AVL after deleting %d\n", key);
}
break;
case 3:
printf("Inorder traversal: ");
inOrder(root);
printf("\n");
break;
case 4:
exit(0);
default:
printf("Invalid choice!\n");
}
}
return 0;
}
=====ooo000000====
DSA_UNIT_4 MRS.MADHAVI A
DSA_UNIT_4 MRS.MADHAVI A