LAB Report
LAB Report
1. Problem Statement
The Tower of Hanoi is a mathematical puzzle where we have three rods and n disks of different sizes.
The objective is to move all disks from one rod to another, adhering to the following rules:
1. Only one disk can be moved at a time.
2. Each move involves taking the top disk from one of the stacks and placing it on another rod.
3. A larger disk may not be placed on top of a smaller disk.
2. Problem Analysis
This problem is a classic example of recursion. The base case is when there's only one disk, and we can
directly move it. For more than one disk, we break the problem into smaller sub-problems by moving
n-1 disks to an auxiliary rod, then moving the largest disk to the target rod, and finally moving the n-
1 disks from the auxiliary rod to the target rod.
3. Algorithm Overview
Tower of Hanoi Process:
1. Move n-1 disks from source rod to auxiliary rod.
2. Move the nth disk (largest) from the source rod to the destination rod.
3. Move n-1 disks from auxiliary rod to destination rod.
Time Complexity: The recursive nature of the algorithm results in an exponential time complexity of
O(2^n).
Space Complexity: Since it uses recursion, the space complexity is O(n) due to the call stack.
4. Source Code
#include<iostream>
using namespace std;
int main() {
int n;
cout << "Enter the number of disks: ";
cin >> n;
towerOfHanoi(n, 'A', 'C', 'B');
return 0;
}
5. Sample Input / Output
Input:
Enter the number of disks: 3
Output:
Move disk 1 from rod A to rod C
Move disk 2 from rod A to rod B
Move disk 1 from rod C to rod B
Move disk 3 from rod A to rod C
Move disk 1 from rod B to rod A
Move disk 2 from rod B to rod C
Move disk 1 from rod A to rod C
6. Remark:
The Tower of Hanoi is a recursive solution with a time complexity of O(2^n), making it inefficient for
large n. However, it demonstrates the power of recursion.
int main() {
int n;
cout << "Enter the array size: ";
cin >> n;
int arr[n];
cout << "Enter the array elements: ";
for (int i = 0; i < n; i++) cin >> arr[i];
bubbleSort(arr, n);
cout << "Sorted array: ";
for (int i = 0; i < n; i++) cout << arr[i] << " ";
return 0;
}
Output:
Sorted array: 12 22 25 34 64
6. Remark:
Bubble sort is a simple sorting algorithm but inefficient for large datasets due to its quadratic time
complexity.
int main() {
int n, x;
cout << "Enter the array size: ";
cin >> n;
int arr[n];
cout << "Enter the array elements: ";
for (int i = 0; i < n; i++) cin >> arr[i];
cout << "Enter the element to be searched: ";
cin >> x;
Output:
Element found at index: 2
6. Remark:
Binary search on unsorted data requires an initial sorting step, making the overall complexity O(n log
n). Hence, it's not efficient compared to linear search for unsorted datasets.
int main() {
int n;
cout << "Enter the array size: ";
cin >> n;
int arr[n];
cout << "Enter the array elements: ";
for (int i = 0; i < n; i++) cin >> arr[i];
quickSort(arr, 0, n - 1);
return 0;
}
Output:
Sorted array: 1 7 8 9 10
6. Remark:
Quick sort is one of the fastest sorting algorithms for large datasets. Its average-case complexity is O(n
log n), but it may degrade to O(n^2) in the worst case.
4. Source Code
#include<iostream>
using namespace std;
bool isEmpty() {
return top == -1;
}
bool push(int x) {
if (top >= MAX - 1) {
cout << "Stack Overflow\n";
return false;
}
stack[++top] = x;
return true;
}
int pop() {
if (isEmpty()) {
cout << "Stack Underflow\n";
return -1;
}
return stack[top--];
}
int peek() {
if (isEmpty()) {
cout << "Stack is Empty\n";
return -1;
}
return stack[top];
}
int main() {
push(10);
push(20);
push(30);
cout << pop() << " Popped from stack\n";
cout << "Top element is: " << peek() << endl;
cout << "Stack is empty: " << (isEmpty() ? "Yes" : "No") << endl;
return 0;
}
6. Remark:
This stack implementation is functional and works efficiently for managing small datasets. Larger data
sets may require dynamic memory allocation.
4. Source Code
#include<iostream>
using namespace std;
bool isEmpty() {
return (front == -1 || front > rear);
}
bool enqueue(int x) {
if (rear >= MAX - 1) {
cout << "Queue Overflow\n";
return false;
}
if (front == -1) front = 0; // First element to be inserted
queue[++rear] = x;
return true;
}
int dequeue() {
if (isEmpty()) {
cout << "Queue Underflow\n";
return -1;
}
return queue[front++];
}
int getFront() {
if (isEmpty()) {
cout << "Queue is Empty\n";
return -1;
}
return queue[front];
}
int main() {
enqueue(10);
enqueue(20);
enqueue(30);
cout << dequeue() << " Dequeued from queue\n";
cout << "Front element is: " << getFront() << endl;
cout << "Queue is empty: " << (isEmpty() ? "Yes" : "No") << endl;
return 0;
}
6. Remark:
This simple queue implementation works for fixed-sized arrays. For dynamic use cases, a circular
queue or dynamically resizable array would be more efficient.