Practical 1
#include <iostream>
#include <string>
using namespace std;
template <class T> class Node {
public:
T data;
Node *next;
Node(const T &data = T(), Node *next = NULL) : data(data), next(next) {}
};
template <class T> class LinkedList {
private:
Node<T> *head;
Node<T> *tail;
public:
LinkedList() : head(NULL), tail(NULL) {}
void insertHead(const T &data) {
Node<T> *newNode = new Node<T>(data);
if (!head) {
head = tail = newNode;
} else {
newNode->next = head;
head = newNode;
}
}
void insertTail(const T &data) {
Node<T> *newNode = new Node<T>(data);
if (!head) {
head = tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
}
void deleteHead() {
if (!head) {
return;
}
Node<T> *temp = head;
head = head->next;
delete temp;
}
void display() {
Node<T> *current = head;
while (current) {
cout << current->data << " ";
current = current->next;
}
cout << endl;
}
};
int main() {
LinkedList<int> intList;
LinkedList<int> strList;
int choice;
do {
cout << "Menu:\n";
cout << "1. Insert Integer at Head\n";
cout << "2. Insert Integer at Tail\n";
cout << "3. Delete Integer from Head\n";
cout << "4. Display Integer List\n";
cout << "5. Insert String at Head\n";
cout << "6. Insert String at Tail\n";
cout << "7. Delete String from Head\n";
cout << "8. Display String List\n";
cout << "9. Exit\n";
cout << "Enter your choice: ";
cin >> choice;
switch (choice) {
case 1:
int data;
cout << "Enter an integer to insert: ";
cin >> data;
intList.insertHead(data);
break;
case 2:
cout << "Enter an integer to insert: ";
cin >> data;
intList.insertTail(data);
break;
case 3:
intList.deleteHead();
break;
case 4:
cout << "Integer List: ";
intList.display();
break;
case 5:
int strData;
cout << "Enter a string to insert: ";
cin >> strData;
strList.insertHead(strData);
break;
case 6:
cout << "Enter a string to insert: ";
cin >> strData;
strList.insertTail(strData);
break;
case 7:
strList.deleteHead();
break;
case 8:
cout << "String List: ";
strList.display();
break;
case 9:
cout << "Exiting program.\n";
break;
default:
cout << "Invalid choice. Please try again.\n";
}
} while (choice != 9);
return 0;
}
Practical 2
#include <iostream>
using namespace std;
template <class T> class DoubleLinkList;
template <class T>
class Node {
T elem;
Node<T> *next;
Node<T> *prev;
public:
Node(T e) {
elem = e;
next = 0;
prev = 0;
}
friend class DoubleLinkList<T>;
};
template <class T> class DoubleLinkList {
Node<T> *head;
Node<T> *tail;
public:
DoubleLinkList() {
head = 0;
tail = 0;
}
DoubleLinkList(Node<T> *&n1) {
head = n1;
head->prev = 0;
head->next = 0;
}
DoubleLinkList(Node<T> *&n1, Node<T> *&n2) {
head = n1;
tail = n2;
head->prev = 0;
tail->next = 0;
head->next = tail;
tail->prev = head;
}
// print function
void printAll() {
Node<T> *currentNode = head;
while (currentNode != 0) {
cout << currentNode->elem << endl;
currentNode = currentNode->next;
}
delete currentNode;
}
// Insertion operations on Double linked list
// 1. Insert at Head
void headInsert(int elem) {
Node<int> *n1 = new Node<int>(elem);
if (head == 0) {
head = n1;
tail = n1;
head->prev = 0;
head->next = 0;
} // if block
else {
n1->next = head;
head->prev = n1;
n1->prev = 0;
head = n1;
} // else block
} // insert at head
// 2. Insert at tail
void tailInsert(int elem) {
Node<int> *n1 = new Node<int>(elem);
if (head == 0) {
head = n1;
head->prev = 0;
head->next = 0;
} // if block
else {
tail->next = n1;
n1->prev = tail;
n1->next = 0;
tail = n1;
} // else block
} // insert at tail
// 3. Delete at Head
void delete_at_head() {
if (head == 0) {
cout << "List is empty ! ";
return;
} // if block
else {
Node<T> *temp = head;
head = head->next;
head->prev = 0;
delete temp;
} // else
}
// 5. Delete at Tail
void delete_at_tail() {
if (head == 0) {
cout << "List is empty ! ";
return;
} // if block
else {
Node<T> *temp = tail;
tail = tail->prev;
tail->next = 0;
delete temp;
} // else
}
};
int main() {
DoubleLinkList<int> l1;
l1.headInsert(5);
l1.headInsert(4);
l1.headInsert(3);
l1.headInsert(2);
l1.headInsert(1);
l1.tailInsert(7);
l1.tailInsert(8);
l1.tailInsert(9);
l1.printAll();
cout << endl;
l1.delete_at_head();
l1.delete_at_tail();
l1.printAll();
return 0;
return 0;
}
Practical 3
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *next;
Node(int data) {
this->data = data;
this->next = nullptr;
};
class CircularLinkedList {
private:
Node *head;
public:
CircularLinkedList() { head = nullptr; }
void insertAtIndex(int data, int index) {
if (index < 0) {
cout << "Invalid index" << endl;
return;
Node *newNode = new Node(data);
Node *current = head;
int currentIndex = 0;
while (current->next != head && currentIndex < index - 1) {
current = current->next;
currentIndex++;
}
newNode->next = current->next;
current->next = newNode;
void deleteAtIndex(int index) {
if (index < 0 || head == nullptr) {
cout << "Invalid index or empty list" << endl;
return;
if (index == 0) {
if (head->next == head) {
delete head;
head = nullptr;
} else {
Node *temp = head;
Node *last = head;
while (last->next != head) {
last = last->next;
head = head->next;
last->next = head;
delete temp;
}
} else {
Node *current = head;
int currentIndex = 0;
while (current->next != head && currentIndex < index - 1) {
current = current->next;
currentIndex++;
if (current->next == head) {
cout << "Invalid index" << endl;
} else {
Node *temp = current->next;
current->next = current->next->next;
delete temp;
void display() {
if (head == nullptr) {
cout << "The list is empty." << endl;
return;
Node *current = head;
do {
cout << current->data << " ";
current = current->next;
} while (current != head);
cout << endl;
~CircularLinkedList() {
if (head == nullptr) {
return;
Node *current = head;
Node *next;
do {
next = current->next;
delete current;
current = next;
} while (current != head);
};
int main() {
CircularLinkedList list;
int choice, data, index;
do {
cout << "Circular Linked List Menu:\n";
cout << "1. Insert at Index\n";
cout << "2. Delete at Index\n";
cout << "3. Display\n";
cout << "4. Exit\n";
cout << "Enter your choice: ";
cin >> choice;
switch (choice) {
case 1:
cout << "Enter data: ";
cin >> data;
cout << "Enter index: ";
cin >> index;
list.insertAtIndex(data, index);
break;
case 2:
cout << "Enter index: ";
cin >> index;
list.deleteAtIndex(index);
break;
case 3:
cout << "Circular Linked List: ";
list.display();
break;
case 4:
cout << "Exiting program." << endl;
break;
default:
cout << "Invalid choice. Please try again." << endl;
break;
} while (choice != 9);
}
Practical 4
Using Array
#include <iostream>
using namespace std;
template <class T>
class MyStack{
T *stack;
int capacity;
int top;
public:
MyStack(){//default Constructor
capacity=0;
stack=new T[capacity];
top=-1;
}
MyStack(int c){//parameterised Constructor
capacity=c;
stack=new T[capacity];
top=-1;
}
bool overFlow(){
if(top==capacity-1){
return true;
}
return false;
}//overflow function
bool empty(){
if(top==-1){
return true;
}
return false;
}//empty function
void push(T elem){
if(this->overFlow()){
cout<<"\nStack is full already\n";
return;
}//if block
top+=1;
stack[top]=elem;
}//push function
T pop(){
if(this->empty()){
cout<<"\nStack is empty already\n";
return -1;
}//if block
top-=1;
return stack[top+1];
}//pop function
void display(){
cout<<"\n Here is the Value of stack \n";
int index=top;
while(index!=-1){
cout<<stack[index]<<endl;
index--;
}
}//display function
T Top(){
return stack[top];
}//top function
};
int main() {
int choice;
int capacity;
cout << "Enter the capacity of the stack: ";
cin >> capacity;
MyStack<int> stack(capacity);
do {
cout << "\nStack Menu:\n";
cout << "1. Push\n";
cout << "2. Pop\n";
cout << "3. Display\n";
cout << "4. Top\n";
cout << "5. Exit\n";
cout << "Enter your choice: ";
cin >> choice;
switch (choice) {
case 1:
int elem;
cout << "Enter element to push: ";
cin >> elem;
stack.push(elem);
break;
case 2:
if (!stack.empty()) {
cout << "Popped element: " << stack.pop() << endl;
} else {
cout << "Stack is empty." << endl;
}
break;
case 3:
stack.display();
break;
case 4:
if (!stack.empty()) {
cout << "Top element: " << stack.Top() << endl;
} else {
cout << "Stack is empty." << endl;
}
break;
case 5:
cout << "Exiting program.\n";
break;
default:
cout << "Invalid choice. Please try again.\n";
}
} while (choice != 5);
return 0;
}
Using Linked list:-
#include <iostream>
using namespace std;
// Define a structure for a single node in the linked list
struct Node
{
int data;
Node *next;
};
// Define the Stack class
class Stack
{
private:
Node *top; // Pointer to the top of the stack
public:
// Constructor to initialize the stack
Stack()
{
top = nullptr;
}
// Function to push an element onto the stack
void push(int value)
{
Node *newNode = new Node();
newNode->data = value;
newNode->next = top;
top = newNode;
}
// Function to pop an element from the stack
void pop()
{
if (isEmpty())
{
cout << "Stack is empty. Cannot pop." << endl;
return;
}
Node *temp = top;
top = top->next;
delete temp;
}
// Function to check if the stack is empty
bool isEmpty()
{
return top == nullptr;
}
// Function to get the top element of the stack
int peek()
{
if (isEmpty())
{
cout << "Stack is empty. Cannot peek." << endl;
return -1; // Return a sentinel value indicating an empty stack
}
return top->data;
}
// Function to display the entire stack
void display()
{
Node *current = top;
cout << "Stack: ";
while (current != nullptr)
{
cout << current->data << " ";
current = current->next;
}
cout << endl;
}
};
int main()
{
Stack stack;
int choice, value;
do
{
cout << "Menu:" << endl;
cout << "1. Push" << endl;
cout << "2. Pop" << endl;
cout << "3. Peek" << endl;
cout << "4. Display" << endl;
cout << "5. Quit" << endl;
cout << "Enter your choice: ";
cin >> choice;
switch (choice)
{
case 1:
cout << "Enter a value to push: ";
cin >> value;
stack.push(value);
break;
case 2:
stack.pop();
break;
case 3:
value = stack.peek();
if (value != -1)
{
cout << "Top element: " << value << endl;
}
break;
case 4:
stack.display();
break;
case 5:
cout << "Quitting the program." << endl;
break;
default:
cout << "Invalid choice. Please try again." << endl;
}
} while (choice != 5);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
// Function to return precedence of operators
int prec(char c)
{
if (c == '^')
return 3;
else if (c == '/' || c == '*')
return 2;
else if (c == '+' || c == '-')
return 1;
else
return -1;
}
// The main function to convert infix expression
// to postfix expression
void infixToPostfix(string s)
{
stack<char> st;
string result;
for (int i = 0; i < s.length(); i++) {
char c = s[i];
// If the scanned character is
// an operand, add it to output string.
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9'))
result += c;
// If the scanned character is an
// ‘(‘, push it to the stack.
else if (c == '(')
st.push('(');
// If the scanned character is an ‘)’,
// pop and add to output string from the stack
// until an ‘(‘ is encountered.
else if (c == ')') {
while (st.top() != '(') {
result += st.top();
st.pop();
}
st.pop();
}
// If an operator is scanned
else {
while (!st.empty()
&& prec(s[i]) <= prec(st.top())) {
result += st.top();
st.pop();
}
st.push(c);
}
}
// Pop all the remaining elements from the stack
while (!st.empty()) {
result += st.top();
st.pop();
}
cout << result << endl;
}
// Driver code
int main()
{
string exp = "((A+B)/C+E/F*G-H)+I";
// Function call
infixToPostfix(exp);
return 0;
}
Practical 5
#include <iostream>
using namespace std;
class Queue {
private:
int capacity;
int size;
int *Q;
int front;
int rear;
public:
Queue() {
capacity = 0;
front = 0;
rear = 0;
size = 0;
Q=new int[capacity];
} // default constructor
Queue(int capacity) {
this->capacity = capacity;
front = 0;
rear = 0;
size = 0;
Q=new int[capacity];
} // parameterized constructor
// Insertion operations
void Insert(int elem) {
if (IsFull()) {
cout << "Queue is full" << endl;
return;
} else {
Q[rear] = elem;
rear = ((rear + 1) % capacity);
size++;
}
} // Insert
// Deletion operations
int Delete() {
if (IsEmpty()) {
cout << "Queue is empty" << endl;
return -1;
} else {
int elem = Q[front];
front = ((front + 1) % capacity);
size--;
return elem;
}
} // Delete
// Utility functions
int Size() { return size; } // Size
bool IsEmpty() { return size == 0; } // IsEmpty
bool IsFull() { return size == capacity; } // IsFull
void Print() {
if (IsEmpty()) {
cout << "Queue is empty" << endl;
return;
} else {
int i = front;
while (i != rear) {
cout << Q[i] << " ";
i = ((i + 1) % capacity);
}
}
}
int Front() {
if (IsEmpty()) {
cout << "Queue is empty" << endl;
return -1;
} else {
return Q[front];
}
}
int Rear() {
if (IsEmpty()) {
cout << "Queue is empty" << endl;
return -1;
} else {
return Q[rear];
}
}
void Clear() {
front = 0;
rear = 0;
size = 0;
}
};
int main() {
int capacity, choice, elem;
cout << "Enter the capacity of the queue: ";
cin >> capacity;
Queue q(capacity);
while (true) {
cout << "\nMenu:\n";
cout << "1. Insert an element\n";
cout << "2. Delete an element\n";
cout << "3. Get the front element\n";
cout << "4. Get the rear element\n";
cout << "5. Check if the queue is empty\n";
cout << "6. Check if the queue is full\n";
cout << "7. Print the queue\n";
cout << "8. Clear the queue\n";
cout << "9. Quit\n";
cout << "Enter your choice: ";
cin >> choice;
switch (choice) {
case 1:
cout << "Enter an element to insert: ";
cin >> elem;
q.Insert(elem);
cout << "Element " << elem << " inserted into the queue.\n";
break;
case 2:
elem = q.Delete();
if (elem != -1)
cout << "Element " << elem << " deleted from the queue.\n";
break;
case 3:
elem = q.Front();
if (elem != -1)
cout << "Front element: " << elem << endl;
break;
case 4:
elem = q.Rear();
if (elem != -1)
cout << "Rear element: " << elem << endl;
break;
case 5:
if (q.IsEmpty())
cout << "Queue is empty.\n";
else
cout << "Queue is not empty.\n";
break;
case 6:
if (q.IsFull())
cout << "Queue is full.\n";
else
cout << "Queue is not full.\n";
break;
case 7:
cout << "Queue: ";
q.Print();
cout << endl;
break;
case 8:
q.Clear();
cout << "Queue cleared.\n";
break;
case 9:
cout << "Exiting the program. Goodbye!\n";
return 0;
default:
cout << "Invalid choice. Please try again.\n";
}
}
return 0;
}
Practical 6
#include <iostream>
#include <algorithm> // For max function
using namespace std;
// Node structure for the binary search tree
struct Node {
int data;
Node* left;
Node* right;
Node(int value) : data(value), left(nullptr), right(nullptr) {}
};
// Insert a value into the binary search tree
Node* insert(Node* root, int value) {
if (root == nullptr) {
return new Node(value);
}
if (value < root->data) {
root->left = insert(root->left, value);
} else if (value > root->data) {
root->right = insert(root->right, value);
}
return root;
}
// In-order traversal of the binary search tree
void inOrderTraversal(Node* root) {
if (root != nullptr) {
inOrderTraversal(root->left);
cout << root->data << " ";
inOrderTraversal(root->right);
}
}
// Pre-order traversal of the binary search tree
void preOrderTraversal(Node* root) {
if (root != nullptr) {
cout << root->data << " ";
preOrderTraversal(root->left);
preOrderTraversal(root->right);
}
}
// Post-order traversal of the binary search tree
void postOrderTraversal(Node* root) {
if (root != nullptr) {
postOrderTraversal(root->left);
postOrderTraversal(root->right);
cout << root->data << " ";
}
}
// Utility function to delete a node with the given value from the binary search
tree
Node* deleteNode(Node* root, int value) {
if (root == nullptr) {
return root;
}
if (value < root->data) {
root->left = deleteNode(root->left, value);
} else if (value > root->data) {
root->right = deleteNode(root->right, value);
} else {
if (root->left == nullptr) {
Node* temp = root->right;
delete root;
return temp;
} else if (root->right == nullptr) {
Node* temp = root->left;
delete root;
return temp;
}
Node* temp = findMin(root->right);
root->data = temp->data;
root->right = deleteNode(root->right, temp->data);
}
return root;
}
// Driver program to test the binary search tree implementation
int main() {
Node* root = nullptr;
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
cout << "In-order traversal: ";
inOrderTraversal(root);
cout << endl;
cout << "Pre-order traversal: ";
preOrderTraversal(root);
cout << endl;
cout << "Post-order traversal: ";
postOrderTraversal(root);
cout << endl;
root = deleteNode(root, 20);
cout << "In-order traversal after deleting 20: ";
inOrderTraversal(root);
cout << endl;
return 0;
}
Practical 7
#include <algorithm>
#include <iostream>
template <typename T> struct AVLNode {
T data;
AVLNode *left;
AVLNode *right;
int height;
AVLNode(const T &val) : data(val), left(NULL), right(NULL), height(1) {}
};
template <typename T> class AVLTree {
private:
AVLNode<T> *root;
int getHeight(AVLNode<T> *node) {
return (node == NULL) ? 0 : node->height;
}
int getBalanceFactor(AVLNode<T> *node) {
return (node == NULL) ? 0 : getHeight(node->left) -getHeight(node->right);
}
AVLNode<T> *rotateRight(AVLNode<T> *y) {
AVLNode<T> *x = y->left;
AVLNode<T> *T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = std::max(getHeight(y->left), getHeight(y->right)) + 1;
x->height = std::max(getHeight(x->left), getHeight(x->right)) + 1;
return x;
}
AVLNode<T> *rotateLeft(AVLNode<T> *x) {
AVLNode<T> *y = x->right;
AVLNode<T> *T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = std::max(getHeight(x->left), getHeight(x->right)) + 1;
y->height = std::max(getHeight(y->left), getHeight(y->right)) + 1;
return y;
}
AVLNode<T> *insert(AVLNode<T> *node, const T &value) {
if (node == NULL) {
return new AVLNode<T>(value);
}
if (value < node->data) {
node->left = insert(node->left, value);
} else if (value > node->data) {
node->right = insert(node->right, value);
} else {
return node; // Duplicate values are not allowed
}
// Update height of current node
node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));
// Get the balance factor to check if this node became unbalanced
int balance = getBalanceFactor(node);
// Left-Left Case
if (balance > 1 && value < node->left->data) {
return rotateRight(node);
}
// Right-Right Case
if (balance < -1 && value > node->right->data) {
return rotateLeft(node);
}
// Left-Right Case
if (balance > 1 && value > node->left->data) {
node->left = rotateLeft(node->left);
return rotateRight(node);
}
// Right-Left Case
if (balance < -1 && value < node->right->data) {
node->right = rotateRight(node->right);
return rotateLeft(node);
}
return node;
}
bool search(AVLNode<T> *node, const T &value) {
if (node == NULL) {
return false;
}
if (value == node->data) {
return true;
} else if (value < node->data) {
return search(node->left, value);
} else {
return search(node->right, value);
}
}
void inorderTraversal(AVLNode<T> *node) {
if (node != NULL) {
inorderTraversal(node->left);
std::cout << node->data << " ";
inorderTraversal(node->right);
}
}
public:
AVLTree() : root(NULL) {}
void insert(const T &value) { root = insert(root, value); }
bool search(const T &value) { return search(root, value); }
void displayInorder() {
inorderTraversal(root);
std::cout << std::endl;
}
AVLNode<T> *getRoot() const { return root; }
};
int main() {
AVLTree<int> myAVL;
myAVL.insert(10);
myAVL.insert(20);
myAVL.insert(30);
myAVL.insert(40);
myAVL.insert(50);
myAVL.insert(25);
std::cout << "Inorder Traversal of AVL Tree: ";
myAVL.displayInorder();
int searchValue = 30;
if (myAVL.search(searchValue)) {
std::cout << "Value " << searchValue << " found in AVL Tree." << std::endl;
} else {
std::cout << "Value " << searchValue << " not found in AVL Tree."
<< std::endl;
}
searchValue = 15;
if (myAVL.search(searchValue)) {
std::cout << "Value " << searchValue << " found in AVL Tree." << std::endl;
} else {
std::cout << "Value " << searchValue << " not found in AVL Tree."
<< std::endl;
}
return 0;
}