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

23UCACCP03-DSA Using C++ Lab1

Uploaded by

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

23UCACCP03-DSA Using C++ Lab1

Uploaded by

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

ARULMIGU ARTHANAREESWARAR ARTS AND SCIENCE

COLLEGE
Affiliated to Periyar University, Salem.
CHITHALANDUR, TIRUCHENGODE, NAMAKKAL - 637 201

RECORD NOTE BOOK


REG NO:

Subject Name: Data Structures and Algorithms Lab Using C++

Subject Code: 23UCACCP03

Certified that this is the bonafide record of the practical


work done by ……………………………………… of Third
Semester, II-BCA in the Computer Science laboratory
during the Academic Year 2024 – 2025.

Staff-in-charge Head of the Department

Submitted for the University Practical


Examination held on…………………………

Internal Examiner External Examiner


ARULMIGU ARTHANAREESWARAR ARTS AND SCIENCE
COLLEGE
Affiliated to Periyar University, Salem.
CHITHALANDUR, TIRUCHENGODE, NAMAKKAL - 637 201

II BCA

DATA STRUCTURES AND ALGORITHMS LAB USING C++


PRACTICAL RECORD
(23UCACCP03)
BACHELOR OF COMPUTER APPLICATIONS
DEPARTMENT OF COMPUTER APPLICATIONS
2024 – 2025
INDEX
Page
Ex.No. Date Title Signature
No.
Write a program to implement the List ADT
1
using arrays and linked lists.
Write a program to implement the following
using a singly linked list.
2
(a) Stack ADT
(b) Queue ADT
Write a program that reads an infix
expression, converts the expression to postfix
3
form and then evaluates the postfix expression
(use stack ADT).
Write a program to implement priority queue
4
ADT.
Write a program to perform the following
operations:
(a) Insert an element into a binary search tree.
5
(b) Delete an element from a binary search tree.
(c) Search for a key element in a binary search
tree
Write a program to perform the following
operations
6
(a) Insertion into an AVL-tree
(b) Deletion from an AVL-tree
Write a program for the implementation of
7
BFS and DFS for a given graph.
Write a programs for implementing the
following searching methods:
8
(a) Linear search
(b) Binary search.
Write a programs for implementing the
following sorting methods:
(a) Bubble sort
9
(b) Selection sort
(c) Insertion sort
(d) Radix sort.
Experiment 1: Write a C++ program to implement the List ADT using Array and Linked
List
(a) List ADT using Arrays
Aim:
The aim of this implementation is to create a List Abstract Data Type (ADT) that allows us to
perform common list operations efficiently.
Prerequisites:
A basic understanding of C++ programming concepts, including arrays, pointers, and linked
lists.
Algorithm (Array Implementation):
1. Create an array: Define an array to store list elements. Let’s call it listArray.
2. Initialize variables:
o curr: Keep track of the number of array elements currently assigned to the list.
o size: Number of items in the list (current size).
o maxsize: Maximum length of the array (maximum list size).
3. Insertion:
o To insert an element at position pos:
▪ Shift all elements from pos to size-1 one position to the right.
▪ Insert the new element at pos.
▪ Update size and curr.
4. Deletion:
o To delete an element at position pos:
▪ Shift all elements from pos+1 to size-1 one position to the left.
▪ Update size and curr.
5. Accessing elements:
o Retrieve an element at position pos using listArray[pos].
Program:
#include <iostream>
const int MAX_SIZE = 100; // Maximum list size
class ListArray {
private:
int listArray[MAX_SIZE];
int curr; // Current number of elements
int size; // Current size of the list
public:
ListArray() {
curr = 0;
size = 0;
}
void insert(int pos, int value) {
if (size >= MAX_SIZE) {
std::cout << "List is full. Cannot insert.\n";
return;
}
for (int i = size; i > pos; --i) {
listArray[i] = listArray[i - 1]; // Shift elements to the right
}
listArray[pos] = value;
++size;
}
void remove(int pos) {
if (pos < 0 || pos >= size) {
std::cout << "Invalid position.\n";
return;
}
for (int i = pos; i < size - 1; ++i) {
listArray[i] = listArray[i + 1]; // Shift elements to the left
}
--size;
}
int get(int pos) {
if (pos < 0 || pos >= size) {
std::cout << "Invalid position.\n";
return -1; // Error value
}
return listArray[pos];
}
};
int main() {
ListArray myList;
myList.insert(0, 10);
myList.insert(1, 20);
myList.insert(2, 30);
std::cout << "Element at position 1: " << myList.get(1) << "\n";
myList.remove(1);
std::cout << "Element at position 1 after removal: " << myList.get(1) << "\n";
return 0;
}
Sample Input and Output:
Suppose we insert elements 10, 20, and 30 at positions 0, 1, and 2, respectively. After removing
the element at position 1, the output will be:
Element at position 1: 20
Element at position 1 after removal: 30
(b) List ADT using Linked Lists
Aim:
The aim of this implementation is to create a dynamic list using a linked list structure. This
program focuses on insertions, deletions, and traversal.
Prerequisites:
A basic understanding of C++ programming concepts, including pointers and classes.
Algorithm (Linked List Implementation):
1. Node Definition:
o Define a Node class with two members: data (to store the list element)
and next (a pointer to the next node).
2. List Class:
o Create a LinkedList class with a private member head (a pointer to the first
node).
o Initialize head to nullptr.
3. Insertion:
o To insert an element at the end:
▪ Create a new node with the given value.
▪ Traverse the list until the last node.
▪ Set the next pointer of the last node to the new node.
o To insert at the beginning:
▪ Create a new node.
▪ Set its next pointer to the current head.
▪ Update head to point to the new node.
4. Deletion:
o To delete an element:
▪ Traverse the list to find the node to be deleted.
▪ Adjust the next pointers to skip the node.
▪ Delete the node.
5. Traversal and Printing:
o Traverse the list from head to the end, printing each element.
Program:
#include <iostream>
class Node {
public:
int data;
Node* next;
Node(int value) {
data = value;
next = nullptr;
}
};
class LinkedList {
private:
Node* head;
public:
LinkedList() {
head = nullptr;
}
void insert(int value) {
Node* newNode = new Node(value);
if (head == nullptr) {
head = newNode;
} else {
Node* temp = head;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = newNode;
}
}
void remove(int value) {
if (head == nullptr) {
std::cout << "List is empty. Cannot delete.\n";
return;
}
if (head->data == value) {
Node* temp = head;
head = head->next;
delete temp;
return;
}
Node* curr = head;
while (curr->next != nullptr && curr->next->data != value) {
curr = curr->next;
}
if (curr->next == nullptr) {
std::cout << "Element not found in the list.\n";
return;
}
Node* temp = curr->next;
curr->next = curr->next->next;
delete temp;
}
void printList() {
Node* temp = head;
while (temp != nullptr) {
std::cout << temp->data << " ";
temp = temp->next;
}
std::cout << std::endl;
}
};
int main() {
LinkedList myList;
myList.insert(10);
myList.insert(20);
myList.insert(30);

std::cout << "Elements of the list: ";


myList.printList();
myList.remove(20);
std::cout << "After deleting 20: ";
myList.printList();
return 0;
}
Sample Input and Output:
Suppose we insert elements 10, 20, and 30 at the end. After deleting the element 20, the output
will be:
Elements of the list: 10 20 30
After deleting 20: 10 30
Experiment 2: Write a C++ program to implement the following using Singly Linked List
(a) Stack ADT
(b) Queue ADT

(a) Stack ADT


Aim:
The aim of this implementation is to create a stack using a singly linked list, allowing
efficient push and pop operations.
Prerequisites:
A basic understanding of C++ programming concepts and pointers.
Algorithm (Linked List Implementation for Stack):

1. Node Definition:
o Define a Node class with two members: data (to store the stack element)
and next (a pointer to the next node).
2. Stack Class:
o Create a Stack class with a private member top (a pointer to the top node).
o Initialize top to nullptr.
3. Push Operation:
o Create a new node with the given value.
o Set its next pointer to the current top.
o Update top to point to the new node.
4. Pop Operation:
o Check if the stack is empty (i.e., top is nullptr).
o If not empty:
▪ Create a temporary pointer (temp) to the top node.
▪ Move top to the next node.
▪ Delete the temp node.
5. Peek Operation:
o Check if the stack is empty.
o If not empty, return the value of the top node.
6. Display Operation:
o Traverse the stack from top to the end, printing each element.

Program:
#include <iostream>
class Node {
public:
int data;
Node* next;
Node(int value) {
data = value;
next = nullptr;
}
};
class Stack {
private:
Node* top;
public:
Stack() {
top = nullptr;
}
void push(int data) {
Node* newNode = new Node(data);
if (!newNode) {
std::cout << "\nStack Overflow\n";
exit(1);
}
newNode->next = top;
top = newNode;
}
bool isEmpty() {
return top == nullptr;
}
int peek() {
if (!isEmpty())
return top->data;
else {
std::cout << "\nStack is empty.\n";
exit(1);
}
}
void pop() {
if (top == nullptr) {
std::cout << "\nStack Underflow\n";
exit(1);
} else {
Node* temp = top;
top = top->next;
delete temp;
}
}
void display() {
Node* temp = top;
while (temp != nullptr) {
std::cout << temp->data << " ";
temp = temp->next;
}
std::cout << std::endl;
}
};
int main() {
Stack myStack;
myStack.push(10);
myStack.push(20);
myStack.push(30);
std::cout << "Elements in the stack: ";
myStack.display();
std::cout << "Top element: " << myStack.peek() << "\n";
myStack.pop();
std::cout << "After popping: ";
myStack.display();
return 0;
}
Sample Input and Output:
Suppose we push elements 10, 20, and 30 into the stack. After popping an element, the output
will be:
Elements in the stack: 30 20 10
Top element: 30
After popping: 20 10

(b) Queue ADT

Aim:

The aim of this implementation is to create a queue using a singly linked list, allowing efficient
enqueue and dequeue operations.

Prerequisites:

A basic understanding of C++ programming concepts and pointers.

Algorithm (Linked List Implementation for Queue):

1. Node Definition:
o Define a Node class with two members: data (to store the queue element)
and next (a pointer to the next node).
2. Queue Class:
o Create a Queue class with a private member front (a pointer to the front node)
and rear (a pointer to the rear node).
o Initialize both front and rear to nullptr.
3. Enqueue Operation:
o Create a new node with the given value.
o If the queue is empty (i.e., rear is nullptr), set both front and rear to the new
node.
o Otherwise, set the next pointer of the current rear to the new node and
update rear to point to the new node.
4. Dequeue Operation:
o Check if the queue is empty (i.e., front is nullptr).
o If not empty:
▪ Create a temporary pointer (temp) to the front node.
▪ Move front to the next node.
▪ Delete the temp node.
5. Peek Operation:
o Check if the queue is empty.
o If not empty, return the value of the front node.
6. Display Operation:
o Traverse the queue from front to the end, printing each element.

Program:
#include <iostream>
class Node {
public:
int data;
Node* next;

Node(int value) {
data = value;
next = nullptr;
}
};
class Queue {
private:
Node* front;
Node* rear;
public:
Queue() {
front = nullptr;
rear = nullptr;
}
void enqueue(int value) {
Node* newNode = new Node(value);
if (rear == nullptr) {
front = rear = newNode;
} else {
rear->next = newNode;
rear = newNode;
}
}
void dequeue() {
if (front == nullptr) {
std::cout << "Queue is empty. Cannot dequeue.\n";
return;
}
Node* temp = front;
front = front->next;
delete temp;
if (front == nullptr) {
rear = nullptr;
}
}
int peek() {
if (front == nullptr) {
std::cout << "Queue is empty.\n";
return -1; // Error value
}
return front->data;
}
void display() {
Node* temp = front;
while (temp != nullptr) {
std::cout << temp->data << " ";
temp = temp->next;
}
std::cout << std::endl;
}
};
int main() {
Queue myQueue;
myQueue.enqueue(10);
myQueue.enqueue(20);
myQueue.dequeue();
myQueue.enqueue(30);
std::cout << "Elements in the queue: ";
myQueue.display();
std::cout << "Front element: " << myQueue.peek() << "\n";
return 0;
}
Sample Input and Output:
Suppose we enqueue elements 10, 20, and 30 into the queue. After dequeuing an element, the
output will be:
Elements in the queue: 20 30
Front element: 20
Experiment 3: Write a program that reads an infix expression, converts the expression
to postfix form and then evaluates the postfix expression (use stack ADT)
Aim:
The aim of this program is to read an infix expression, convert it to postfix form, and then
evaluate the postfix expression using a stack.
Prerequisites:
A basic understanding of C++ programming concepts, including stacks and string
manipulation.
Algorithm:
1. Infix to Postfix Conversion:
o Create an empty stack for storing operators and a string for storing the result
(postfix expression).
o Scan the infix expression from left to right.
o If the scanned character is an operand (digit or variable), append it to the result.
o If the scanned character is an operator:
▪ Pop operators from the stack to the result until the top of the stack has
an operator of lower precedence or the stack is empty.
▪ Push the scanned operator onto the stack.
o If the scanned character is ‘(’, push it onto the stack.
o If the scanned character is ‘)’, pop operators from the stack to the result until ‘(’
is encountered, and pop ‘(’ from the stack.
o After all characters are scanned, pop the remaining operators from the stack to
the result.
2. Postfix Evaluation:
o Create an empty stack for storing operands.
o Iterate through the postfix expression:
▪ If the element is an operand, push it onto the stack.
▪ If the element is an operator, pop two operands from the stack, apply the
operator, and push the result back into the stack.
o The final result will be the top element of the stack.
Program:
#include <iostream>
#include <stack>
#include <string>
#include <cctype>
using namespace std;
int precedence(char op) {
if (op == '+' || op == '-')
return 1;
if (op == '*' || op == '/')
return 2;
return 0;
}
string infixToPostfix(string infix) {
stack<char> st;
string postfix = "";
for (char c : infix) {
if (isalnum(c))
postfix += c;
else if (c == '(')
st.push(c);
else if (c == ')') {
while (!st.empty() && st.top() != '(') {
postfix += st.top();
st.pop();
}
st.pop(); // Pop '('
} else {
while (!st.empty() && precedence(c) <= precedence(st.top())) {
postfix += st.top();
st.pop();
}
st.push(c);
}
}
while (!st.empty()) {
postfix += st.top();
st.pop();
}
return postfix;
}
int evaluatePostfix(string postfix) {
stack<int> operands;
for (char c : postfix) {
if (isdigit(c))
operands.push(c - '0');
else {
int op2 = operands.top();
operands.pop();
int op1 = operands.top();
operands.pop();
switch (c) {
case '+': operands.push(op1 + op2); break;
case '-': operands.push(op1 - op2); break;
case '*': operands.push(op1 * op2); break;
case '/': operands.push(op1 / op2); break;
}
}
}
return operands.top();
}
int main() {
string infix = "2+3*1-9";
cout << "Infix Expression: " << infix << endl;
string postfix = infixToPostfix(infix);
cout << "Postfix Expression: " << postfix << endl;
int result = evaluatePostfix(postfix);
cout << "Result: " << result << endl;
return 0;
}
Sample Input and Output:
Suppose we input the infix expression “2+3*1-9”. The program will output:
Infix Expression: 2+3*1-9
Postfix Expression: 231*+9-
Result: -4
Experiment 4: Write a program to implement priority queue ADT
Aim:
The aim of this program is to create a priority queue (max heap by default) using the C++
Standard Template Library (STL).
Prerequisites:
A basic understanding of C++ programming concepts.
Algorithm:
1. Priority Queue Implementation:
o We’ll use the std::priority_queue class from the STL.
o By default, it creates a max heap (largest element at the top).
o To create a min heap (smallest element at the top), we’ll use a custom
comparison function.
o The syntax for creating a min heap is: std::priority_queue<int, vector<int>,
greater<int>> pq;
o Here, int is the type of elements you want to store in the priority queue. You can
replace int with any other data type you need.
o vector<int> is the type of internal container used to store these elements.
o greater<int> is a custom comparison function that sets up a min-heap. It means
that the smallest element will be at the top of the queue.
o In the case of a max heap (default), we don’t need to specify the comparison
function.
Program:
#include <iostream>
#include <queue>
int main() {
std::priority_queue<int> pq; // Max heap by default
// Insert elements into the priority queue
pq.push(10);
pq.push(20);
pq.push(5);
pq.push(15);
std::cout << "Priority Queue (Max Heap): ";
while (!pq.empty()) {
std::cout << pq.top() << " ";
pq.pop();
}
std::cout << std::endl;
return 0;
}
Sample Output:
Priority Queue (Max Heap): 20 15 10 5
Experiment 5: Write a program to perform the following operations
• Insert an element into a binary search tree.
• Delete an element from a binary search tree.
• Search for a key element in a binary search tree.

Aim:
The aim of this program is to perform basic operations on a binary search tree (BST), including
insertion, deletion, and searching.
Prerequisites:
A basic understanding of C++ programming concepts.
Algorithm:
1. Insertion into a Binary Search Tree (BST):
1. If the tree is empty, create a new node with the given value and make it the root.
2. Otherwise, traverse the tree:
▪ If the value is less than the current node’s value, move to the left subtree.
▪ If the value is greater than the current node’s value, move to the right
subtree.
▪ Repeat until an empty position is found.
3. Insert the new node at the appropriate position.
2. Deletion from a Binary Search Tree (BST):
1. Find the node to be deleted.
2. If the node has no children, simply delete it.
3. If the node has one child, replace it with its child.
4. If the node has two children, find the in-order successor (or predecessor), copy
its value to the node, and recursively delete the successor (or predecessor).
3. Searching for a Key Element in a Binary Search Tree (BST):
1. Start from the root.
2. If the current node’s value matches the key, return true.
3. If the key is less than the current node’s value, move to the left subtree.
4. If the key is greater than the current node’s value, move to the right subtree.
5. Repeat until a match is found or the tree is exhausted.
Program:
#include <iostream>
struct TreeNode {
int key;
TreeNode* left;
TreeNode* right;
};
TreeNode* newNode(int value) {
TreeNode* temp = new TreeNode;
temp->key = value;
temp->left = temp->right = nullptr;
return temp;
}
TreeNode* insert(TreeNode* root, int value) {
if (root == nullptr)
return newNode(value);
if (value < root->key)
root->left = insert(root->left, value);
else if (value > root->key)
root->right = insert(root->right, value);
return root;
}
TreeNode* findMin(TreeNode* root) {
while (root->left != nullptr)
root = root->left;
return root;
}
TreeNode* deleteNode(TreeNode* root, int key) {
if (root == nullptr)
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 == nullptr) {
TreeNode* temp = root->right;
delete root;
return temp;
} else if (root->right == nullptr) {
TreeNode* temp = root->left;
delete root;
return temp;
}
TreeNode* temp = findMin(root->right);
root->key = temp->key;
root->right = deleteNode(root->right, temp->key);
}
return root;
}
bool search(TreeNode* root, int key) {
if (root == nullptr)
return false;
if (root->key == key)
return true;
else if (key < root->key)
return search(root->left, key);
else
return search(root->right, key);
}
void inorderTraversal(TreeNode* root) {
if (root == nullptr)
return;
inorderTraversal(root->left);
std::cout << root->key << " ";
inorderTraversal(root->right);
}
int main() {
TreeNode* root = nullptr;
int choice, key;
do {
std::cout << "\n1. Insert\n2. Delete\n3. Search\n4. Display (Inorder)\n5. Exit\n";
std::cout << "Enter your choice: ";
std::cin >> choice;
switch (choice) {
case 1:
std::cout << "Enter key to insert: ";
std::cin >> key;
root = insert(root, key);
break;
case 2:
std::cout << "Enter key to delete: ";
std::cin >> key;
root = deleteNode(root, key);
break;
case 3:
std::cout << "Enter key to search: ";
std::cin >> key;
std::cout << (search(root, key) ? "Found" : "Not found") << std::endl;
break;
case 4:
std::cout << "Inorder traversal: ";
inorderTraversal(root);
std::cout << std::endl;
break;
case 5:
std::cout << "Exiting program.\n";
break;
default:
std::cout << "Invalid choice. Try again.\n";
}
} while (choice != 5);
return 0;
}
Sample Input and Output:
Suppose we perform the following operations:
1. Insert 50, 30, 20, 40, 70, 60, and 80.
2. Delete 30.
3. Search for 60.
The program will output:
1. Insert
2. Delete
3. Search
4. Display (Inorder)
5. Exit
Enter your choice: 1
Enter key to insert: 50

1. Insert
2. Delete
3. Search
4. Display (Inorder)
5. Exit
Enter your choice: 1
Enter key to insert: 30

...

1. Insert
2. Delete
3. Search
4. Display (Inorder)
5. Exit
Enter your choice: 4
Inorder traversal: 20 40 50 60 70 80

1. Insert
2. Delete
3. Search
4. Display (Inorder)
5. Exit
Enter your choice: 2
Enter key to delete: 30

1. Insert
2. Delete
3. Search
4. Display (Inorder)
5. Exit
Enter
Experiment 6: Write a program to perform the following operations
• Insertion into an AVL-tree
• Deletion from an AVL-tree
Aim:
The aim of this program is to implement insertion and deletion operations on an AVL tree in
C++ using switch-case statements.
Prerequisites:
1. Understanding of AVL trees and their balancing criteria.
2. Basic knowledge of C++ programming language.
3. Familiarity with binary search trees (BSTs) and their operations.
Algorithm:
1. Insertion:
● Start with a recursive insertion function.
● Perform normal BST insertion.
● Update the height of each node after insertion.
● Check for balance factor of each node to ensure AVL property is maintained.
● If the balance factor is violated, perform rotations (left-left, left-right, right-
right, right-left) to balance the tree.
2. Deletion:
● Start with a recursive deletion function.
● Perform normal BST deletion.
● Update the height of each node after deletion.
● Check for balance factor of each node to ensure AVL property is maintained.
● If the balance factor is violated, perform rotations (left-left, left-right, right-
right, right-left) to balance the tree.
Program:
#include <iostream>
using namespace std;
// AVL Tree Node Structure
struct Node {
int key;
Node *left;
Node *right;
int height;
};
// Function to create a new AVL tree node
Node* newNode(int key) {
Node* node = new Node();
node->key = key;
node->left = nullptr;
node->right = nullptr;
node->height = 1;
return node;
}
// Function to get the height of a node
int height(Node* node) {
if (node == nullptr)
return 0;
return node->height;
}
// Function to get the balance factor of a node
int balanceFactor(Node* node) {
if (node == nullptr)
return 0;
return height(node->left) - height(node->right);
}
// Function to right rotate a subtree rooted with y
Node* rightRotate(Node* y) {
Node* x = y->left;
Node* T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = max(height(y->left), height(y->right)) + 1;
x->height = max(height(x->left), height(x->right)) + 1;
// Return new root
return x;
}
// Function to left rotate a subtree rooted with x
Node* leftRotate(Node* x) {
Node* y = x->right;
Node* T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = max(height(x->left), height(x->right)) + 1;
y->height = max(height(y->left), height(y->right)) + 1;
// Return new root
return y;
}
// Function to perform AVL tree insertion
Node* insert(Node* root, int key) {
// Perform normal BST insertion
if (root == nullptr)
return newNode(key);
if (key < root->key)
root->left = insert(root->left, key);
else if (key > root->key)
root->right = insert(root->right, key);
else // Duplicate keys not allowed
return root;
// Update height of this ancestor node
root->height = 1 + max(height(root->left), height(root->right));
// Get the balance factor to check if this node became unbalanced
int balance = balanceFactor(root);
// Left Left Case
if (balance > 1 && key < root->left->key)
return rightRotate(root);
// Right Right Case
if (balance < -1 && key > root->right->key)
return leftRotate(root);
// Left Right Case
if (balance > 1 && key > root->left->key) {
root->left = leftRotate(root->left);
return rightRotate(root);
}
// Right Left Case
if (balance < -1 && key < root->right->key) {
root->right = rightRotate(root->right);
return leftRotate(root);
}
// Return the unchanged node pointer
return root;
}
// Function to find the node with minimum key value in a tree
Node* minValueNode(Node* node) {
Node* current = node;
// Loop down to find the leftmost leaf
while (current->left != nullptr)
current = current->left;
return current;
}
// Function to perform AVL tree deletion
Node* deleteNode(Node* root, int key) {
// Perform normal BST deletion
if (root == nullptr)
return root;
if (key < root->key)
root->left = deleteNode(root->left, key);
else if (key > root->key)
root->right = deleteNode(root->right, key);
else {
// Node with only one child or no child
if (root->left == nullptr || root->right == nullptr) {
Node* temp = root->left ? root->left : root->right;
// No child case
if (temp == nullptr) {
temp = root;
root = nullptr;
} else // One child case
*root = *temp; // Copy the contents of the non-empty child
delete temp;
} else {
// Node with two children, get the inorder successor
Node* temp = minValueNode(root->right);
// Copy the inorder successor's data to this node
root->key = temp->key;
// Delete the inorder successor
root->right = deleteNode(root->right, temp->key);
}
}
// If the tree had only one node then return
if (root == nullptr)
return root;
// Update height of the current node
root->height = 1 + max(height(root->left), height(root->right));
// Get the balance factor to check if this node became unbalanced
int balance = balanceFactor(root);
// Left Left Case
if (balance > 1 && balanceFactor(root->left) >= 0)
return rightRotate(root);
// Left Right Case
if (balance > 1 && balanceFactor(root->left) < 0) {
root->left = leftRotate(root->left);
return rightRotate(root);
}
// Right Right Case
if (balance < -1 && balanceFactor(root->right) <= 0)
return leftRotate(root);
// Right Left Case
if (balance < -1 && balanceFactor(root->right) > 0) {
root->right = rightRotate(root->right);
return leftRotate(root);
}
return root;
}
// Function to perform inorder traversal of the AVL tree
void inorder(Node* root) {
if (root != nullptr) {
inorder(root->left);
cout << root->key << " ";
inorder(root->right);
}
}
int main() {
Node* root = nullptr;
int choice, key;

do {
cout << "\nAVL Tree Operations:";
cout << "\n1. Insertion";
cout << "\n2. Deletion";
cout << "\n3. Inorder Traversal";
cout << "\n4. Exit";
cout << "\nEnter your choice: ";
cin >> choice;
switch (choice) {
case 1:
cout << "Enter key to insert: ";
cin >> key;
root = insert(root, key);
cout << "Inserted " << key << " into the AVL tree.\n";
break;
case 2:
cout << "Enter key to delete: ";
cin >> key;
root = deleteNode(root, key);
cout << "Deleted " << key << " from the AVL tree.\n";
break;
case 3:
cout << "Inorder traversal of AVL tree: ";
inorder(root);
cout << endl;
break;
case 4:
cout << "Exiting...";
break;
default:
cout << "Invalid choice! Please enter a valid option.\n";
}
} while (choice != 4);
return 0;
}
Sample Input/Output:

AVL Tree Operations:


1. Insertion
2. Deletion
3. Inorder Traversal
4. Exit
Enter your choice: 1
Enter key to insert: 10
Inserted 10 into the AVL tree.

AVL Tree Operations:


1. Insertion
2. Deletion
3. Inorder Traversal
4. Exit
Enter your choice: 1
Enter key to insert: 5
Inserted 5 into the AVL tree.

AVL Tree Operations:


1. Insertion
2. Deletion
3. Inorder Traversal
4. Exit
Enter your choice: 1
Enter key to insert: 15
Inserted 15 into the AVL tree.

AVL Tree Operations:


1. Insertion
2. Deletion
3. Inorder Traversal
4. Exit
Enter your choice: 3
Inorder traversal of AVL tree: 5 10 15

AVL Tree Operations:


1. Insertion
2. Deletion
3. Inorder Traversal
4. Exit
Enter your choice: 2
Enter key to delete: 10
Deleted 10 from the AVL tree.

AVL Tree Operations:


1. Insertion
2. Deletion
3. Inorder Traversal
4. Exit
Enter your choice: 3
Inorder traversal of AVL tree: 5 15

AVL Tree Operations:


1. Insertion
2. Deletion
3. Inorder Traversal
4. Exit
Enter your choice: 4
Exiting...
Experiment 7: Write a program for implementation of BFS and DFS for a given graph.
Aim:
The aim of this program is to traverse a given graph using both BFS and DFS algorithms.
Prerequisites:
Before proceeding, ensure you have a basic understanding of C++ programming concepts and
familiarity with graphs.
Algorithm for BFS (Breadth-First Search):
1. Start from a source vertex (usually the first vertex).
2. Create an empty queue and enqueue the source vertex.
3. Mark the source vertex as visited.
4. While the queue is not empty:
o Dequeue a vertex from the queue.
o Process the vertex (print or perform any other operation).
o Enqueue all unvisited neighbors of the dequeued vertex.
o Mark the neighbors as visited.
5. Repeat step 4 until the queue is empty.
Algorithm for DFS (Depth-First Search):
1. Start from a source vertex (usually the first vertex).
2. Create an empty stack and push the source vertex onto the stack.
3. Mark the source vertex as visited.
4. While the stack is not empty:
o Pop a vertex from the stack.
o Process the vertex (print or perform any other operation).
o Push all unvisited neighbors of the popped vertex onto the stack.
o Mark the neighbors as visited.
5. Repeat step 4 until the stack is empty.
Program:
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <limits> // for numeric_limits
class Graph {
private:
int vertices;
std::vector<std::vector<int>> adjList;
public:
Graph(int V) : vertices(V) {
adjList.resize(V);
}
void addEdge(int u, int v) {
adjList[u].push_back(v);
adjList[v].push_back(u); // For an undirected graph
}
void bfs(int start) {
std::vector<bool> visited(vertices, false);
std::queue<int> q;
q.push(start);
visited[start] = true;
std::cout << "BFS traversal starting from vertex " << start << ": ";
while (!q.empty()) {
int curr = q.front();
q.pop();
std::cout << curr << " ";
for (int neighbor : adjList[curr]) {
if (!visited[neighbor]) {
q.push(neighbor);
visited[neighbor] = true;
}
}
}
std::cout << std::endl;
}
void dfs(int start) {
std::vector<bool> visited(vertices, false);
std::stack<int> s;
s.push(start);
std::cout << "DFS traversal starting from vertex " << start << ": ";
while (!s.empty()) {
int curr = s.top();
s.pop();
if (!visited[curr]) {
std::cout << curr << " ";
visited[curr] = true;
for (int neighbor : adjList[curr]) {
if (!visited[neighbor])
s.push(neighbor);
}
}
}
std::cout << std::endl;
}
};
int getIntInput(const std::string& prompt) {
int value;
while (true) {
std::cout << prompt;
std::cin >> value;
if (std::cin.fail()) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Invalid input. Please enter an integer.\n";
} else {
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return value;
}
}
}
int main() {
int V = getIntInput("Enter the number of vertices: ");
int E = getIntInput("Enter the number of edges: ");
Graph g(V);
std::cout << "Enter " << E << " edges (u v): ";
for (int i = 0; i < E; ++i) {
int u = getIntInput("Enter u: ");
int v = getIntInput("Enter v: ");
g.addEdge(u, v);
}
int choice;
do {
std::cout << "\n1. BFS\n2. DFS\n3. Exit\n";
choice = getIntInput("Enter your choice: ");
switch (choice) {
case 1: {
int start_bfs = getIntInput("Enter the starting vertex for BFS: ");
g.bfs(start_bfs);
break;
}
case 2: {
int start_dfs = getIntInput("Enter the starting vertex for DFS: ");
g.dfs(start_dfs);
break;
}
case 3:
std::cout << "Exiting program.\n";
break;
default:
std::cout << "Invalid choice. Try again.\n";
}
} while (choice != 3);
return 0;
}
Sample Input and Output:
0 -- 1
| |
2 -- 3
| |
4–5
Sample input:
67
01
02
13
23
24
35
45
Sample output:
1. BFS
2. DFS
3. Exit
Enter your choice: 1
Enter the starting vertex for BFS: 0
BFS traversal starting from vertex 0: 0 1 2 3 4 5

1. BFS
2. DFS
3. Exit
Enter your choice: 2
Enter the starting vertex for DFS: 0
DFS traversal starting from vertex 0: 0 2 4 5 3 1

1. BFS
2. DFS
3. Exit
Enter your choice: 3
Exiting program.
Experiment 8: Write a program for implementing the following searching methods.
(a) Linear Search
(b) Binary Search
(a) Linear Search
Aim:
The aim of this program is to search for a given element in an array using linear search.
Prerequisites:
Before proceeding, ensure you have a basic understanding of C++ programming concepts.
Algorithm:
1. Start from the leftmost element of the array.
2. Compare the search key with each element of the array.
3. If the key matches an element, return the index.
4. If the key doesn’t match any element, return -1.
Program:
#include <iostream>
using namespace std;
int linearSearch(int arr[], int n, int x) {
for (int i = 0; i < n; i++) {
if (arr[i] == x)
return i;
}
return -1;
}
int main() {
int arr[] = {2, 3, 4, 10, 40};
int x = 10;
int n = sizeof(arr) / sizeof(arr[0]);
int result = linearSearch(arr, n, x);
if (result == -1)
cout << "Element is not present in the array";
else
cout << "Element is present at index " << result;
return 0;
}
Sample Output:
Element is present at index 3

(b) Binary Search


Aim:
The aim of this program is to search for a given element in a sorted array using binary search.
Prerequisites:
Before proceeding, ensure you have a basic understanding of C++ programming concepts.
Algorithm:
1. Start with the entire sorted array.
2. Compare the middle element with the target value.
3. If the middle element is equal to the target value, return its index.
4. If the target value is smaller than the middle element, search in the left half of the current
space.
5. If the target value is greater than the middle element, search in the right half of the
current space.
6. Repeat steps 2-5 until the target element is found or the search space is exhausted.
Program:
#include <iostream>
using namespace std;
int binarySearch(int arr[], int low, int high, int x) {
while (low <= high) {
int mid = low + (high - low) / 2;
if (arr[mid] == x)
return mid;
if (arr[mid] < x)
low = mid + 1;
else
high = mid - 1;
}
return -1;
}
int main() {
int arr[] = {2, 3, 4, 10, 40};
int x = 10;
int n = sizeof(arr) / sizeof(arr[0]);
int result = binarySearch(arr, 0, n - 1, x);
if (result == -1)
cout << "Element is not present in the array";
else
cout << "Element is present at index " << result;
return 0;
}
Sample Output:
Element is present at index 3
Experiment 9: Write a program for implementing the following sorting methods.
a) Bubble sort
b) Selection sort
c) Insertion sort
d) Radix sort

(a) Bubble Sort


Aim:
The aim of this program is to sort an array using the bubble sort algorithm.
Prerequisites:
Before proceeding, ensure you have a basic understanding of C++ programming concepts.
Algorithm:
1. The bubble sort algorithm repeatedly compares adjacent elements in the array and
swaps them if they are in the wrong order.
2. This process is repeated for each element in the array until the entire array is sorted.
Program:
#include <iostream>
using namespace std;
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < n - i - 1; ++j) {
if (arr[j] > arr[j + 1]) {
// Swap elements
swap(arr[j], arr[j + 1]);
}
}
}
}
void printArray(int arr[], int size) {
for (int i = 0; i < size; ++i) {
cout << arr[i] << " ";
}
cout << endl;
}
int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Original array: ";
printArray(arr, n);
bubbleSort(arr, n);
cout << "Sorted array: ";
printArray(arr, n);
return 0;
}
Sample Output:
Original array: 64 25 12 22 11
Sorted array: 11 12 22 25 64

(b) Selection Sort


Aim:
The aim of this program is to sort an array using the selection sort algorithm.
Prerequisites:
Before proceeding, ensure you have a basic understanding of C++ programming concepts.
Algorithm:
1. The selection sort algorithm sorts an array by repeatedly finding the minimum element
(considering ascending order) from the unsorted part and putting it at the beginning.
2. The algorithm maintains two subarrays in the given array:
o The subarray that is already sorted.
o The remaining subarray that is unsorted.
3. In every iteration of selection sort, the minimum element (considering ascending order)
from the unsorted subarray is picked and moved to the sorted subarray.
Program:
#include <iostream>
using namespace std;
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; ++i) {
int min_idx = i;
for (int j = i + 1; j < n; ++j) {
if (arr[j] < arr[min_idx])
min_idx = j;
}
swap(arr[i], arr[min_idx]);
}
}
int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Original array: ";
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
cout << endl;
selectionSort(arr, n);
cout << "Sorted array: ";
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
cout << endl;
return 0;
}
Sample Output:
Original array: 64 25 12 22 11
Sorted array: 11 12 22 25 64

(c) Insertion Sort


Aim:
The aim of this program is to sort an array using the insertion sort algorithm.
Prerequisites:
Before proceeding, ensure you have a basic understanding of C++ programming concepts.
Algorithm:
1. The insertion sort algorithm works by dividing the array into two parts: a sorted
subarray and an unsorted subarray.
2. Initially, the first element of the array is considered as a sorted subarray.
3. Start with the element at index 1 and store it in a variable called key.
4. Compare the current element (key) with the elements in the sorted subarray from right
to left (elements at indices from j = i-1 to j = 0).
5. Shift elements greater than the key one position to the right to make space for the
current element until it finds a smaller element than the key and j is not zero.
6. When the correct position for the key is found, insert it at arr[j + 1].
7. Repeat these steps for the remaining elements of the unsorted subarray until the
complete array is sorted.
Program:
#include <iostream>
using namespace std;
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; ++i) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
void printArray(int arr[], int n) {
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
cout << endl;
}
int main() {
int arr[] = {12, 11, 13, 5, 6};
int N = sizeof(arr) / sizeof(arr[0]);
cout << "Original array: ";
printArray(arr, N);
insertionSort(arr, N);
cout << "Sorted array: ";
printArray(arr, N);
return 0;
}
Sample Output:
Original array: 12 11 13 5 6
Sorted array: 5 6 11 12 13

(d) Radix Sort


Aim:
The aim of this program is to sort an array using the Radix Sort algorithm.
Prerequisites:
Before proceeding, ensure you have a basic understanding of C++ programming concepts.
Algorithm:
1. Radix Sort is a non-comparative sorting algorithm that sorts data with integer keys by
grouping the keys based on each digit’s value.
2. It processes the elements digit by digit, from the least significant digit (rightmost) to
the most significant digit (leftmost).
3. Radix Sort uses counting sort as a subroutine to sort an array of numbers.
Program:
#include <iostream>
using namespace std;
// Function to get the maximum element from an array
int getMax(int arr[], int n) {
int max_val = arr[0];
for (int i = 1; i < n; ++i) {
if (arr[i] > max_val)
max_val = arr[i];
}
return max_val;
}
// Using counting sort to sort the elements based on significant places
void countingSort(int arr[], int n, int exp) {
int output[n];
int count[10] = {0};
// Calculate count of elements for each digit
for (int i = 0; i < n; ++i)
count[(arr[i] / exp) % 10]++;
// Calculate cumulative count
for (int i = 1; i < 10; ++i)
count[i] += count[i - 1];
// Place the elements in sorted order
for (int i = n - 1; i >= 0; --i) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
// Copy the sorted elements back to the original array
for (int i = 0; i < n; ++i)
arr[i] = output[i];
}
// Main function to implement radix sort
void radixSort(int arr[], int n) {
int max_val = getMax(arr, n);
// Apply counting sort to sort elements based on place value
for (int exp = 1; max_val / exp > 0; exp *= 10)
countingSort(arr, n, exp);
}
// Function to print the array
void printArray(int arr[], int n) {
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
cout << endl;
}
int main() {
int arr[] = {170, 45, 75, 90, 802, 24, 2, 66};
int n = sizeof(arr) / sizeof(arr[0]);
cout << "Original array: ";
printArray(arr, n);
radixSort(arr, n);
cout << "Sorted array: ";
printArray(arr, n);
return 0;
}
Sample Output:
Original array: 170 45 75 90 802 24 2 66
Sorted array: 2 24 45 66 75 90 170 802

You might also like