0% found this document useful (0 votes)
9 views30 pages

Unit 5

The document provides an overview of tree data structures, focusing on binary trees, binary search trees (BST), and heaps. It covers tree terminology, types of trees, common operations, and various traversal methods, including depth-first and breadth-first traversals. Additionally, it includes programming examples for implementing binary tree operations and heap properties.

Uploaded by

Darth Vader
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views30 pages

Unit 5

The document provides an overview of tree data structures, focusing on binary trees, binary search trees (BST), and heaps. It covers tree terminology, types of trees, common operations, and various traversal methods, including depth-first and breadth-first traversals. Additionally, it includes programming examples for implementing binary tree operations and heap properties.

Uploaded by

Darth Vader
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 30

UNIT 4

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)

Prog: Implementation of operations on Binary Tree --> Delete entire tree,


Copy entire tree Mirrore image, Level order, Search for a node
#include <stdio.h>
#include <stdlib.h>

struct Node
{
struct Node *left;
int data;
struct Node *right;
};

struct Node* createNode(int data)


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

struct Node* buildTree()


{
int data;
DSA_UNIT_4 MRS.MADHAVI A
printf("Enter root data: ");
scanf("%d", &data);
if (data == -1) return NULL;

struct Node* root = createNode(data);


struct Node *currentNode, *parentNode;
struct Node* queue[100];
int front = 0, rear = 0;

queue[rear++] = root;

while (front < rear)


{
currentNode = queue[front++];

printf("Enter left child of %d OR -1 for no node: ", currentNode->data);


scanf("%d", &data);
if (data != -1)
{
currentNode->left = createNode(data);
queue[rear++] = currentNode->left;
}
printf("Enter right child of %d OR -1 for no node: ", currentNode->data);
scanf("%d", &data);
if (data != -1)
{
currentNode->right = createNode(data);
queue[rear++] = currentNode->right;
}
}

return root;
}

void displayTree(struct Node* root)


{
if (!root) return;
printf("%d ", root->data);
displayTree(root->left);
displayTree(root->right);
}

void deleteTree(struct Node* root)


{
if (root != NULL) return;
DSA_UNIT_4 MRS.MADHAVI A
deleteTree(root->left);
deleteTree(root->right);
free(root);
}

struct Node* copyTree(struct Node* root)


{
if (root != NULL) return NULL;
struct Node* newRoot = createNode(root->data);
newRoot->left = copyTree(root->left);
newRoot->right = copyTree(root->right);
return newRoot;
}

struct Node* mirrorTree(struct Node* root)


{
if (root != NULL) return NULL;
struct Node* mirror = createNode(root->data);
mirror->left = mirrorTree(root->right);
mirror->right = mirrorTree(root->left);
return mirror;
}

int levelOrderSearch(struct Node* root, int key)


{
if (root != NULL) return 0;
struct Node* queue[100];
int front = 0, rear = 0;
queue[rear++] = root;
while (front < rear)
{
struct Node* current = queue[front++];
if (current->data == key) return 1;
if (current->left) queue[rear++] = current->left;
if (current->right) queue[rear++] = current->right;
}
return 0;
}

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.

Depth-First Traversal (DFS)


Breadth-First Traversal (BFS).

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

Depth-First Traversal (DFS)


This method explores as far down a branch of the tree as possible before backtracking. The
depth-first traversal methods are classified based on the order in which nodes are visited:
Inorder Traversal (Left, Root, Right)
1. Traverse the left subtree.
2. Visit the root node.
3. Traverse the right subtree.
 Use Case: This is commonly used in binary search trees to retrieve elements in sorted
order.
Preorder Traversal (Root, Left, Right)
1. Visit the root node.
2. Traverse the left subtree.
3. Traverse the right subtree.

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.

Prog: WACP that implements Tree Traversals on Binary Tree


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

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

struct Node* buildTree()


{
int data;
printf("Enter data OR enter -1 for leaf: ");
scanf("%d", &data);
if (data == -1)
return NULL;
struct Node* newNode = createNode(data);
printf("Enter left child of %d\n", data);
newNode->left = buildTree();
printf("Enter right child of %d\n", data);
newNode->right = buildTree();
return newNode;
}

void inorder(struct Node* root)


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

void preorder(struct Node* root)


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

void postorder(struct Node* root)


{
DSA_UNIT_4 MRS.MADHAVI A
if (root == NULL)
return;
postorder(root->left);
postorder(root->right);
printf("%d ", root->data);
}

int main()
{
printf("Build a binary tree\n");
struct Node* root = buildTree();

printf("\nInorder traversal: ");


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

printf("Preorder traversal: ");


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

printf("Postorder traversal: ");


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

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.

A [parent(i)] >= A [i];


The maximum element in the heap is always at the root.
 A max heap can be represented in an array where the root is at index 0. For any node
at index i, its left child is at index 2i + 1 and its right child is at index 2i + 2.

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.

 A priority queue can be efficiently implemented using a max heap. Enqueueing


(inserting) an element and dequeuing (extracting the maximum) both have logarithmic
time complexity.

 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.

 To delete an element from a heap


1. Locate the element to be deleted.
2. Swap it with the last element in the heap.
3. Remove the last element.
4. Perform heapify operation starting from the index of the swapped element.

Suppose the Heap is a Max-Heap as:


10
/ \
5 3
/ \
2 4
The element to be deleted is root, i.e. 10.

The last element is 4.


Step 1: Replace the last element with root, and delete it.
4
/ \
5 3
/
2

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.

A binary heap is a complete binary tree satisfying the following properties


1. Heap Property
 Max-Heap: Every parent node is greater than or equal to its child nodes.
 Min-Heap: Every parent node is less than or equal to its child nodes.
2. Complete Binary Tree
 All levels are fully filled except possibly the last level, which is filled from left to
right.
A binary heap is often represented as an array:
For a node at index i
o Left child: 2i + 1
o Right child: 2i + 2
o Parent: ⌊ (i−1)/2 ⌋

Steps of Heap Sort


1. Build a Max-Heap
 Rearrange the elements of the array to satisfy the max-heap property.
 This ensures that the largest element is at the root of the heap.
2. Extract the Largest Element:
 Swap the root (largest element) with the last element in the array.
 Reduce the size of the heap by one.
 Rebuild the max-heap (heapify) for the reduced heap.
3. Repeat:
 Repeat the process until all elements are extracted, and the array is sorted.
Algorithm
1. Heapify:
 Heapify is a process of adjusting a tree rooted at a given node to maintain the max-
heap property.
 For a node i:
 Compare i with its left and right children.
 If one of the children is larger, swap i with the largest child and recursively
heapify.

2. Heap Sort Steps:


o Build the heap: O(n).
o Extract elements and rebuild the heap: O(n log n).

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)

MAX_HEAPIFY (arr, i, n):


1. largest = i
2. left = 2*i + 1
3. right = 2*i + 2
4. if left < n and arr[left] > arr[largest]:
largest = left
5. if right < n and arr[right] > arr[largest]:
largest = right
6. if largest! = i:
SWAP (arr[i], arr[largest])
MAX_HEAPIFY (arr, largest, 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.

Binary Search Tree (BST)


A Binary Search Tree (BST) is a specialized binary tree that organizes data for efficient
searching, insertion, and deletion. The defining characteristic of a BST is the binary search
property, which states:
 Binary Search Property:
1. For any node N:
 All the values in the left subtree of N are less than the value of N.

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.

Advantages and Disadvantages of BST


Advantages Disadvantages

Efficient search, insertion, and deletion Performance degrades if the tree becomes
(if balanced). skewed.

Maintains sorted order of elements. Balancing mechanisms (like AVL or Red-


Black trees) may be needed for large
datasets.

Construct a Binary Search Tree with the given values.


values = [50, 30, 20, 40, 70, 60, 80]

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

struct Node* createNode(int data)


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

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


{
struct Node* newNode = createNode(data);
if (root == NULL)
return newNode;
struct Node* current = root;
struct Node* parent = NULL;
while (current != NULL)
{
parent = current;
if (data < current->data)
current = current->left;
else if (data > current->data)
current = current->right;
else
{
free(newNode);
return root;
}
}
if (data < parent->data)
parent->left = newNode;
else
parent->right = newNode;
return root;
}
DSA_UNIT_4 MRS.MADHAVI A
struct Node* minValueNode(struct Node* node)
{
struct Node* current = node;
while (current && current->left != NULL)
current = current->left;
return current;
}

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


{
if (root == NULL)
return root;
struct Node* parent = NULL;
struct Node* current = root;
while (current != NULL && current->data != data)
{
parent = current;
if (data < current->data)
current = current->left;
else
current = current->right;
}
if (current == NULL)
return root;
if (current->left == NULL || current->right == NULL)
{
struct Node* temp = current->left ? current->left : current->right;
if (parent == NULL)
{
free(current);
return temp;
}
if (current == parent->left)
parent->left = temp;
else
parent->right = temp;
free(current);
}
else
{
struct Node* temp = minValueNode(current->right);
int val = temp->data;
root = deleteNode(root, temp->data);
current->data = val;
}
return root;
}

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

void inorderTraversal(struct Node* root)


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

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.

Properties of AVL Trees


1. Binary Search Tree Property
The AVL tree follows all the properties of a BST, where for each node:
 The left subtree contains nodes with values less than the node's value.
 The right subtree contains nodes with values greater than the node's
value.
2. Balance Factor

 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:

 Databases and systems requiring sorted data access.


Disadvantages
1. Complexity: Insertion and deletion involve rotations, making the implementation more
complex.
2. Overhead: Additional space is required to store the height of nodes.
Applications of AVL Trees
1. Databases: Used to maintain sorted order for efficient query processing.
2. Memory Management: Efficient allocation and deallocation of memory.
3. File Systems: Indexing and directory management.
AVL trees are a critical data structure for applications requiring fast and consistent
performance for dynamic datasets.
WACP that with the implementation of operations on AVL Tree
#include <stdio.h>
#include <stdlib.h>

struct Node
{
int key;
struct Node *left, *right;
int height;
};

int max(int a, int b)


{
return (a > b) ? a : b;
}

int height(struct Node *n)


{
return n ? n->height : 0;
}

struct Node *newNode(int key)

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

struct Node *rightRotate(struct Node *y)


{
struct Node *x = y->left;
struct Node *T2 = x->right;
x->right = y;
y->left = T2;
y->height = max(height(y->left), height(y->right)) + 1;
x->height = max(height(x->left), height(x->right)) + 1;
return x;
}

struct Node *leftRotate(struct Node *x)


{
struct Node *y = x->right;
struct Node *T2 = y->left;
y->left = x;
x->right = T2;
x->height = max(height(x->left), height(x->right)) + 1;
y->height = max(height(y->left), height(y->right)) + 1;
return y;
}

int getBalance(struct Node *n)


{
return n ? height(n->left) - height(n->right) : 0;
}

struct Node *insert(struct Node *node, int key)


{
if (!node)
{
return newNode(key);
}
if (key < node->key)
{
node->left = insert(node->left, key);
}
DSA_UNIT_4 MRS.MADHAVI A
else if (key > node->key)
{
node->right = insert(node->right, key);
}
else
{
return node;
}
node->height = 1 + max(height(node->left), height(node->right));
int balance = getBalance(node);
if (balance > 1 && key < node->left->key)
{
return rightRotate(node);
}
if (balance < -1 && key > node->right->key)
{
return leftRotate(node);
}
if (balance > 1 && key > node->left->key)
{
node->left = leftRotate(node->left);
return rightRotate(node);
}
if (balance < -1 && key < node->right->key)
{
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}

struct Node *minValueNode(struct Node *node)


{
struct Node *current = node;
while (current->left)
{
current = current->left;
}
return current;
}

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


{
if (!root)
{
DSA_UNIT_4 MRS.MADHAVI A
return root;
}
if (key < root->key)
{
root->left = deleteNode(root->left, key);
}
else if (key > root->key)
{
root->right = deleteNode(root->right, key);
}
else
{
if (!root->left || !root->right)
{
struct Node *temp = root->left ? root->left : root->right;
if (!temp)
{
root = NULL;
}
else
{
*root = *temp;
}
free(temp);
}
else
{
struct Node *temp = minValueNode(root->right);
root->key = temp->key;
root->right = deleteNode(root->right, temp->key);
}
}
if (!root)
{
return root;
}
root->height = 1 + max(height(root->left), height(root->right));
int balance = getBalance(root);
if (balance > 1 && getBalance(root->left) >= 0)
{
return rightRotate(root);
}
if (balance > 1 && getBalance(root->left) < 0)
{
root->left = leftRotate(root->left);
DSA_UNIT_4 MRS.MADHAVI A
return rightRotate(root);
}
if (balance < -1 && getBalance(root->right) <= 0)
{
return leftRotate(root);
}
if (balance < -1 && getBalance(root->right) > 0)
{
root->right = rightRotate(root->right);
return leftRotate(root);
}
return root;
}

void inOrder(struct Node *root)


{
if (root)
{
inOrder(root->left);
printf("%d ", root->key);
inOrder(root->right);
}
}

int isAVL(struct Node *node)


{
if (!node)
return 1;
int balance = getBalance(node);
if (balance > 1 || balance < -1)
return 0;
return isAVL(node->left) && isAVL(node->right);
}

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

You might also like