Experiment: 1 (A) : Compiler Requirement: Algorithm
Experiment: 1 (A) : Compiler Requirement: Algorithm
EXPERIMENT : 1 (a)
AIM : WAP to implement Merge Sort using array as a data structure & analyze its time and space
complexity .
Compiler Requirement : Dev C++
Algorithm :
In the following algorithm, arr is the given array, beg is the starting element, and end is the
last element of the array.
MERGE_SORT(arr, beg, end)
if beg < end
set mid = (beg + end)/2
MERGE_SORT(arr, beg, mid)
MERGE_SORT(arr, mid + 1, end)
MERGE (arr, beg, mid, end)
end of if
END MERGE_SORT
CODE :
#include <bits/stdc++.h>
using namespace std;
right++;
}
}
OUTPUT :
Complexity :
Time Complexity : O(NlogN)
EXPERIMENT : 1 (b)
AIM : WAP to implement Quick Sort using array as a data structure and analyze its time and space
complexity.
Compiler Requirement : Dev C++
Algorithm :
In the following algorithm, A is the given array :-
qs (array A, start, end) {
if (start < end) {
p = partition(A, start, end)
qs (A, start, p - 1)
qs (A, p + 1, end)
}
}
CODE :
#include <bits/stdc++.h>
using namespace std;
while (i < j) {
while (arr[i] <= pivot && i <= high - 1) {
i++;
}
while (arr[j] > pivot && j >= low + 1) {
j--;
}
if (i < j) swap(arr[i], arr[j]);
5
}
swap(arr[low], arr[j]);
return j;
}
void qs(vector<int> &arr, int low, int high) {
if (low < high) {
int pIndex = partition(arr, low, high);
qs(arr, low, pIndex - 1);
qs(arr, pIndex + 1, high);
}
}
vector<int> quickSort(vector<int> arr) {
qs(arr, 0, arr.size() - 1);
return arr;
}
int main()
{
vector<int> arr = {4, 6, 2, 5, 7, 9, 1, 3};
int n = arr.size();
cout << "\n\t\tBefore Using quick Sort: \n" << endl<<"\t";
for (int i = 0; i < n; i++)
{
cout << arr[i] << " ";
}
cout << endl<<"----------------------------------\n";
arr = quickSort(arr);
cout << "\n\t\tAfter Using quick sort: \n\n"<<"\t";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
6
OUTPUT :
Complexity :
Time Complexity : O(N*logN) , where N = size of the array
.
7
EXPERIMENT : 1 (c)
AIM : WAP to implement Bubble Sort using array as a data structure and analyze its time and space
complexity .
Compiler Requirement : Dev C++
Algorithm :
In the following algorithm, A is the given array :-
Declare variables as i , j , temp;
for(i=0 -> i< n){
for(j = i+1 -> j < n) {
if(a[j] < a[i]) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
CODE :
#include <bits/stdc++.h>
using namespace std;
void print(int a[], int n) {
int i;
for(i = 0; i < n; i++) {
cout << a[i] << " "; }
}
void bubble(int a[], int n) {
int i, j, temp;
for(i = 0; i < n; i++) {
for(j = i+1; j < n; j++) {
if(a[j] < a[i]) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
8
}
}
}
int main () {
int i, j,temp;
int a[5] = { 10, 35, 32, 13, 26};
int n = sizeof(a)/sizeof(a[0]);
cout<<"\n\t\tBefore sorting array elements are - \n\n\t";
print(a, n);
cout<<"\n--------------------------------------------";
bubble(a, n);
cout<<"\n\t\tAfter sorting array elements are - \n\n\t";
print(a, n);
return 0;
}
OUTPUT :
Complexity :
Time Complexity : O(N2) , where N = size of the array
EXPERIMENT : 1 (d)
AIM : WAP to implement Selection Sort using array as a data structure and analyze its time and space
complexity .
Compiler Requirement : Dev C++
Algorithm :
In the following algorithm, A is the given array :-
Declaring a function to perform selection sort..
for(i=0 -> i<n){
mini = i
for(j=i+1 -> j<n){
if(arr[j] < arr[mini])
mini = j;
}
swap( arr[i] , arr[mini])
}
CODE :
#include<bits/stdc++.h>
using namespace std;
void selection_sort(int arr[], int n) {
for(int i=0 ;i<n-1 ;i++){
int mini = i;
for(int j=i+1 ; j<n ;j++){
if(arr[j] < arr[mini]){
mini = j;
}
}
int temp = arr[mini];
arr[mini] = arr[i];
arr[i] = temp;
}
cout<<"\n----------------------------------\n";
cout << "\t\tAfter Selection Sort" << endl<<"\t";
10
OUTPUT :
Complexity :
Time Complexity : O(N2) , where N = size of the array
EXPERIMENT : 1 (e)
AIM : WAP to implement Heap Sort using array as a data structure and analyze its time and space
complexity .
Compiler Requirement : Dev C++
Algorithm :
HeapSort(arr)
BuildMaxHeap(arr)
i = length(arr) to 2
swap arr[1] with arr[i]
heap_size[arr] = heap_size[arr] ? 1
MaxHeapify(arr,1)
End
BuildMaxHeap(arr)
heap_size(arr) = length(arr)
for i = length(arr)/2 to 1
MaxHeapify(arr,i)
End
MaxHeapify(arr,i)
L = left(i) R = right(i)
if L ? heap_size[arr] and arr[L] > arr[i]
largest = L
else largest = i
if R ? heap_size[arr] and arr[R] > arr[largest]
largest = R
if largest != i
swap arr[i] with arr[largest]
MaxHeapify(arr,largest)
End
CODE :
#include <iostream>
using namespace std;
void heapify(int a[], int n, int i){
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
12
OUTPUT :
Complexity :
Time Complexity : O(NlogN) , where N = size of the array
.
14
EXPERIMENT : 2 (a)
AIM : WAP to implement Linear Search and analyze its time complexity .
Compiler Requirement : Dev C++
Theory :
Linear Search (also known as Sequential Search) is a straightforward algorithm used to find a specific
value within a list or array. The algorithm working is as follows :--
Linear search is typically used when dealing with unsorted or small lists, where sorting the list would be
inefficient compared to a simple search.
Algorithm :
CODE :
#include <iostream>
using namespace std;
int linearSearch(int arr[], int size, int target) {
for (int i = 0; i < size; ++i) {
if (arr[i] == target) {
15
return i;
}
}
return -1;
}
int main() {
int n, target;
cout << "Enter the number of elements: ";
cin >> n;
int *arr = new int[n];
cout << "Enter the elements:\n";
for (int i = 0; i < n; ++i) {
cin >> arr[i];
}
cout << "Enter the target element to search for: ";
cin >> target;
int result = linearSearch(arr, n, target);
if (result != -1) {
cout << "\n-----------------------------------\n";
cout << "Element found at index " << result << endl;
} else {
cout << "\n-----------------------------------\n";
cout << "Element not found\n";
}
delete[] arr;
return 0;
}
OUTPUT :
16
Complexity :
Time Complexity :
Best Case: O(1) , The best-case scenario occurs when the target value is found at the very first
position of the list or array. Here, the algorithm only needs one comparison.
Average Case: O(n) , On average, if the target value is located somewhere in the middle of the list,
the algorithm will need to traverse approximately half of the elements.
Worst Case: O(n) , The worst-case scenario occurs when the target value is either not present in
the list or is found at the very last position. In this case, the algorithm needs to check every single
element in the list.
EXPERIMENT : 2 (b)
AIM : WAP to implement Binary Search and analyze its time complexity.
Compiler Requirement : Dev C++
Theory :
Binary Search is a highly efficient algorithm used to find a specific value within a sorted array or list. The
key idea behind binary search is to repeatedly divide the search interval in half, thereby reducing the
problem size exponentially with each step. This method leverages the sorted nature of the array to
quickly zero in on the target value.
Algorithm :
Initialization:
o Set two pointers: left to the index of the first element (0) and right to the
index of the last element (n - 1 where n is the number of elements in the
array).
Calculate the Middle:
o Compute the middle index of the current interval using :-
Mid = left + ( right – left ) / 2
Comparison:
o Compare the target value with the element at the middle index :-
If the target is equal to the middle element: The target is found.
Return the middle index.
If the target is less than the middle element: Adjust the right
pointer to mid - 1 (narrow the search to the left half).
If the target is greater than the middle element: Adjust the left
pointer to mid + 1 (narrow the search to the right half).
Repeat:
o Repeat steps 2 and 3 until the left pointer exceeds the right pointer. If
the target value is not found after the pointers cross, return -1 or another
indication that the value is not present in the array.
CODE :
#include <algorithm>
#include <iostream>
using namespace std;
int binarySearch(int arr[], int size, int target) {
int left = 0;
int right = size - 1;
18
OUTPUT :
.
20
Complexity :
Time Complexity :
Best Case: O(1) , The best case occurs when the target value is located at the middle index
of the array on the first comparison.
Average Case: O(log n) , On average, binary search will require log₂(n) comparisons, where
n is the number of elements in the array, because the search space is halved with each
step.
Worst Case: O(log n) , In the worst case, binary search requires log₂(n) comparisons when
the target is located at the far end of the search space or not present in the array
Space Complexity :
Iterative Version: O(1) , When implemented iteratively, binary search requires a constant
amount of extra space, as it only uses a few additional variables for pointers and indices.
Recursive Version: O(log n) , When implemented recursively, the space complexity is O(log n)
due to the function call stack. Each recursive call adds a new frame to the call stack, and the
maximum depth of recursion is proportional to the logarithm of the number of elements
21
EXPERIMENT : 3
AIM : WAP to implement Matrix multiplication & analyze its time complexity.
Compiler Requirement : Dev C++
Theory :
Strassen's Matrix Multiplication is the divide and conquer approach to solve the matrix multiplication
problems. The usual matrix multiplication method multiplies each row with each column to achieve the
product matrix. The time complexity taken by this approach is O(n3), since it takes two loops to multiply.
Strassen’s method was introduced to reduce the time complexity from O(n3) to O(nlog 7).
Algorithm :
In this context, using Strassen’s Matrix multiplication algorithm, the time consumption can be
improved a little bit.
CODE :
#include <iostream>
#include <vector>
using namespace std;
typedef vector<vector<int>> Matrix;
Matrix add(const Matrix &A, const Matrix &B) {
int n = A.size();
Matrix C(n, vector<int>(n));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
C[i][j] = A[i][j] + B[i][j];
}
}
return C;
}
Matrix subtract(const Matrix &A, const Matrix &B) {
int n = A.size();
Matrix C(n, vector<int>(n));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
C[i][j] = A[i][j] - B[i][j];
}
}
return C;
}
Matrix strassen(const Matrix &A, const Matrix &B) {
int n = A.size();
if (n == 1) {
Matrix C(1, vector<int>(1));
C[0][0] = A[0][0] * B[0][0];
23
return C;
}
int newSize = n / 2;
Matrix A11(newSize, vector<int>(newSize));
Matrix A12(newSize, vector<int>(newSize));
Matrix A21(newSize, vector<int>(newSize));
Matrix A22(newSize, vector<int>(newSize));
Matrix B11(newSize, vector<int>(newSize));
Matrix B12(newSize, vector<int>(newSize));
Matrix B21(newSize, vector<int>(newSize));
Matrix B22(newSize, vector<int>(newSize));
for (int i = 0; i < newSize; ++i) {
for (int j = 0; j < newSize; ++j) {
A11[i][j] = A[i][j];
A12[i][j] = A[i][j + newSize];
A21[i][j] = A[i + newSize][j];
A22[i][j] = A[i + newSize][j + newSize];
B11[i][j] = B[i][j];
B12[i][j] = B[i][j + newSize];
B21[i][j] = B[i + newSize][j];
B22[i][j] = B[i + newSize][j + newSize];
}
}
Matrix P1 = strassen(add(A11, A22), add(B11, B22));
Matrix P2 = strassen(add(A21, A22), B11);
Matrix P3 = strassen(A11, subtract(B12, B22));
Matrix P4 = strassen(A22, subtract(B21, B11));
Matrix P5 = strassen(add(A11, A12), B22);
Matrix P6 = strassen(subtract(A21, A11), add(B11, B12));
Matrix P7 = strassen(subtract(A12, A22), add(B21, B22));
24
};
Matrix B = {
{16, 15, 14, 13},
{12, 11, 10, 9},
{8, 7, 6, 5},
{4, 3, 2, 1}
};
cout << "Matrix A:" << endl;
printMatrix(A);
cout << "Matrix B:" << endl;
printMatrix(B);
Matrix C = strassen(A, B);
cout << "Matrix C (A * B):" << endl;
printMatrix(C);
return 0;
}
OUTPUT :
26
Complexity :
Time Complexity :
.
27
EXPERIMENT : 4
AIM : WAP to implement solution for knapsack problem using greedy method.
Compiler Requirement : Dev C++
Algorithm :
In this , A set of n items, where each item i has a value v[i] and a weight w[i] id taken as input
.The maximum capacity of the knapsack is W. The maximum value that can be
accommodated in the knapsack, possibly with fractional parts of items as the output .
CODE :
#include <bits/stdc++.h>
using namespace std;
struct Item {
int value, weight;
int curWeight = 0;
OUTPUT :
Complexity :
Time Complexity : O(N*LogN)
.
30
EXPERIMENT : 5
AIM : WAP to implement job sequencing with deadlines .
Compiler Requirement : Dev C++
Algorithm :
Input is n jobs, each with a profit p[i] and a deadline d[i] .
Sort jobs in decreasing order of profit. This ensures that more profitable jobs are
considered first.
Initialize a schedule with max_deadline slots (equal to the maximum deadline
among the jobs), initially all set to empty.
Iterate over each job:
o For each job i, find the latest available time slot before its deadline (d[i]).
o If a slot is found, assign the job to that slot and add its profit to the total.
Stop once all jobs have been considered or all slots are filled.
CODE :
#include <algorithm>
#include <iostream>
using namespace std;
struct Job {
char id;
int dead;
int profit;
};
int result[n];
31
bool slot[n];
int main(){
Job arr[] = { { 'a', 2, 100 },
{ 'b', 1, 19 },
{ 'c', 2, 27 },
{ 'd', 1, 25 },
{ 'e', 3, 15 } };
OUTPUT :
Complexity :
Time Complexity : O(n²)
.
33
EXPERIMENT : 6
AIM : WAP to implement Huffman coding and analyze its time complexity .
Compiler Requirement : Dev C++
Algorithm :
Input A set of n characters, each with a frequency f[i] representing how often they occur
and in output , the Huffman codes for each character and the binary encoded data.
Repeat until there is only one node left, which will be the root of the Huffman
tree.
Traverse the Huffman tree from the root to each leaf node (character). Assign a
binary code to each character: append a 0 for left traversal and a 1 for right traversal.
CODE :
#include <bits/stdc++.h>
using namespace std;
struct MinHeapNode {
char data;
unsigned freq;
MinHeapNode *left, *right;
MinHeapNode(char data, unsigned freq){
left = right = NULL;
this->data = data;
34
this->freq = freq;
}
};
struct compare {
bool operator()(MinHeapNode* l, MinHeapNode* r) {
return (l->freq > r->freq);
}
};
void printCodes(struct MinHeapNode* root, string str) {
if (!root)
return;
if (root->data != '$')
cout << root->data << ": " << str << "\n";
printCodes(root->left, str + "0");
printCodes(root->right, str + "1");
}
void HuffmanCodes(char data[], int freq[], int size) {
struct MinHeapNode *left, *right, *top;
priority_queue<MinHeapNode*, vector<MinHeapNode*>, compare>
minHeap;
for (int i = 0; i < size; ++i)
minHeap.push(new MinHeapNode(data[i], freq[i]));
while (minHeap.size() != 1) {
left = minHeap.top();
minHeap.pop();
right = minHeap.top();
minHeap.pop();
top = new MinHeapNode('$',
left->freq + right->freq);
top->left = left;
35
top->right = right;
minHeap.push(top);
}
printCodes(minHeap.top(), "");
}
int main() {
char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
int freq[] = { 5, 9, 12, 13, 16, 45 };
int size = sizeof(arr) / sizeof(arr[0]);
HuffmanCodes(arr, freq, size);
return 0;
}
OUTPUT :
Complexity :
Time Complexity : O(n log n)
.
36
EXPERIMENT : 7 (a)
AIM : WAP to implement minimum spanning tree using Prim’s Algorithm and analyze its time & space
complexity.
Compiler Requirement : Dev C++
Algorithm :
Follow the given steps to utilize the Prim’s Algorithm mentioned above for finding MST of a
graph:
Create a set mstSet that keeps track of vertices already included in MST.
Assign a key value to all vertices in the input graph. Initialize all key values as
INFINITE. Assign the key value as 0 for the first vertex so that it is picked first.
While mstSet doesn’t include all vertices
o Pick a vertex u that is not there in mstSet and has a minimum key value.
o Include u in the mstSet.
o Update the key value of all adjacent vertices of u. To update the key values,
iterate through all adjacent vertices.
o For every adjacent vertex v, if the weight of edge u-v is less than the previous
key value of v, update the key value as the weight of u-v.
CODE :
#include <bits/stdc++.h>
using namespace std;
#define V 5
int main(){
int graph[V][V] = { { 0, 2, 0, 6, 0 },
{ 2, 0, 3, 8, 5 },
{ 0, 3, 0, 0, 7 },
38
{ 6, 8, 0, 0, 9 },
{ 0, 5, 7, 9, 0 } };
primMST(graph);
return 0;
}
OUTPUT :
Complexity :
Time Complexity : O(V2) using an adjacency matrix and O((V +E) log V) using an adjacency list, where
V is the number of vertices and E is the number of edges in the graph
Space Complexity : O(V+E) for the priority queue and O(V2) for the adjacency matrix representation
.
39
EXPERIMENT : 7 (b)
AIM : WAP to implement minimum spanning tree using Kruskal’s Algorithm and analyze its time & space
complexity.
Compiler Requirement : Dev C++
Algorithm :
The inputs taken by the kruskal’s algorithm are the graph G {V, E}, where V is the
set of vertices and E is the set of edges, and the source vertex S and the minimum
spanning tree of graph G is obtained as an output.
Sort all the edges in the graph in an ascending order and store it in
an array edge[].
Construct the forest of the graph on a plane with all the vertices in
it.
Select the least cost edge from the edge[] array and add it into the
forest of the graph. Mark the vertices visited by adding them into
the visited[] array.
Repeat the steps 2 and 3 until all the vertices are visited without
having any cycles forming in the graph
When all the vertices are visited, the minimum spanning tree is
formed.
Calculate the minimum cost of the output spanning tree formed.
CODE :
#include <bits/stdc++.h>
using namespace std;
class DSU {
int* parent;
int* rank;
public:
DSU(int n) {
parent = new int[n];
rank = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = -1;
rank[i] = 1;
40
}
}
int find(int i){
if (parent[i] == -1)
return i;
return parent[i] = find(parent[i]);
}
void unite(int x, int y) {
int s1 = find(x);
int s2 = find(y);
if (s1 != s2) {
if (rank[s1] < rank[s2]) {
parent[s1] = s2;
}
else if (rank[s1] > rank[s2]) {
parent[s2] = s1;
}
else {
parent[s2] = s1;
rank[s1] += 1;
}
}
}
};
class Graph {
vector<vector<int> > edgelist;
int V;
public:
Graph(int V) { this->V = V; }
41
void kruskals_mst() {
sort(edgelist.begin(), edgelist.end());
DSU s(V);
int ans = 0;
cout << "Following are the edges in the constructed MST"<< endl;
for (auto edge : edgelist) {
int w = edge[0];
int x = edge[1];
int y = edge[2];
if (s.find(x) != s.find(y)) {
s.unite(x, y);
ans += w;
cout << x << " -- " << y << " == " << w
<< endl;
}
}
cout << "Minimum Cost Spanning Tree: " << ans;
}
};
int main() {
Graph g(4);
g.addEdge(0, 1, 10);
g.addEdge(1, 3, 15);
g.addEdge(2, 3, 4);
g.addEdge(2, 0, 6);
42
g.addEdge(0, 3, 5);
g.kruskals_mst();
return 0;
}
OUTPUT :
Complexity :
Time Complexity : O(E logV), here E is number of Edges and V is number of vertices in graph
Space Complexity : O(V + E), here V is the number of vertices and E is the number of edges in the
graph.
.
43
EXPERIMENT : 8
AIM : WAP to implement Dijkstra’s Algorithm and analyze its complexity.
Compiler Requirement : Dev C++
Algorithm :
Create a set sptSet (shortest path tree set) that keeps track of vertices included in the
shortest path tree, i.e., whose minimum distance from the source is calculated and finalized.
Initially, this set is empty.
Assign a distance value to all vertices in the input graph. Initialize all distance values
as INFINITE. Assign the distance value as 0 for the source vertex so that it is picked
first.
While sptSet doesn’t include all vertices
o Pick a vertex u which is not there in sptSet and has minimum distance
value.
o Include u to sptSet.
o Update the distance value of all adjacent vertices of u. To update the
distance values, iterate through all adjacent vertices. For every adjacent
vertex v, if the sum of the distance value of u (from source) and weight of
edge u-v, is less than the distance value of v, then update the distance
value of v.
CODE :
#include <limits.h>
#include <stdio.h>
#define V 9
int minDistance(int dist[], bool sptSet[]){
int min = INT_MAX, min_index;
for (int v = 0; v < V; v++)
if (sptSet[v] == false && dist[v] <= min)
min = dist[v], min_index = v;
return min_index;
}
int main(){
int graph[V][V] = { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },
{ 4, 0, 8, 0, 0, 0, 0, 11, 0 },
{ 0, 8, 0, 7, 0, 4, 0, 0, 2 },
{ 0, 0, 7, 0, 9, 14, 0, 0, 0 },
{ 0, 0, 0, 9, 0, 10, 0, 0, 0 },
{ 0, 0, 4, 14, 10, 0, 2, 0, 0 },
{ 0, 0, 0, 0, 0, 2, 0, 1, 6 },
45
{ 8, 11, 0, 0, 0, 0, 1, 0, 7 },
{ 0, 0, 2, 0, 0, 0, 6, 7, 0 } };
dijkstra(graph, 0);
return 0;
}
OUTPUT :
Complexity :
Time Complexity : O(V2)
.
46
EXPERIMENT : 9
AIM : WAP to implement Bellman Ford algorithm and analyze its time & space complexities .
Compiler Requirement : Dev C++
Algorithm :
Shortest distance to all vertices from src (source vertex). If there is a negative weight cycle,
then shortest distances are not calculated, negative weight cycle is reported.
This step initializes distances from source to all vertices as infinite and distance to
source itself as 0. Create an array dist[] of size |V| with all values as infinite except
dist[src] where src is source vertex.
This step calculates shortest distances. Do following |V|-1 times where |V| is the
number of vertices in given graph. Do following for each edge u-v :-
If dist[v] > dist[u] + weight of edge uv, then update dist[v]
dist[v] = dist[u] + weight of edge uv
This step reports if there is a negative weight cycle in graph. Do following for each
edge u-v :--
If dist[v] > dist[u] + weight of edge uv, then “Graph contains negative
weight cycle”
The idea of step 3 is, step 2 guarantees shortest distances if graph doesn’t contain
negative weight cycle. If we iterate through all edges one more time and get a
shorter path for any vertex, then there is a negative weight cycle
CODE :
#include <bits/stdc++.h>
using namespace std;
}
}
for (int i = 0; i < E; i++) {
int x = graph[i][0];
int y = graph[i][1];
int weight = graph[i][2];
if (dis[x] != INT_MAX &&
dis[x] + weight < dis[y])
cout << "Graph contains negative weight cycle"<< endl;
}
cout << "Vertex Distance from Source" << endl;
for (int i = 0; i < V; i++)
cout << i << "\t\t" << dis[i] << endl;
}
int main(){
int V = 5;
int E = 8;
int graph[][3] = { { 0, 1, -1 }, { 0, 2, 4 },
{ 1, 2, 3 }, { 1, 3, 2 },
{ 1, 4, 2 }, { 3, 2, 5 },
{ 3, 1, 1 }, { 4, 3, -3 } };
BellmanFord(graph, V, E, 0);
return 0;
}
48
OUTPUT :
Complexity :
Time Complexity : O(VE) , where V is no. of vertices & E is no. of edges
EXPERIMENT : 10
AIM : WAP to implement N – Queen’s Problem using backtracking .
Compiler Requirement : Dev C++
Algorithm :
Start in the leftmost column
If all queens are placed return true
Try all rows in the current column. Do the following for every row.
o If the queen can be placed safely in this row
Then mark this [row, column] as part of the solution and recursively
check if placing queen here leads to a solution.
If placing the queen in [row, column] leads to a solution then
return true.
If placing queen doesn’t lead to a solution then unmark this [row,
column] then backtrack and try other rows.
o If all rows have been tried and valid solution is not found return false to
trigger backtracking.
CODE :
#include <bits/stdc++.h>
using namespace std;
bool solveNQ(int n) {
vector<vector<int>> board(n, vector<int>(n, 0));
if (solveNQUtil(board, 0) == false) {
cout << "Solution does not exist";
return false;
}
printSolution(board);
return true;
}
int main() {
int n = 4;
solveNQ(n);
return 0;
}
OUTPUT :
Complexity :
Time Complexity : O(N!)
EXPERIMENT : 11
AIM : WAP to implement Matrix Chain Multiplication via dynamic programming and analyze its
complexity .
Compiler Requirement : Dev C++
Algorithm :
Set m[i][i]=0m[i][i] = 0m[i][i]=0 for all iii, as multiplying a single matrix incurs no
multiplication cost.
Recurrence Relation:
The minimum cost of multiplying all matrices from A1A_1A1 to AnA_nAn is stored in
m[1][n]m[1][n]m[1][n].
CODE :
#include <iostream>
#include <limits.h>
using namespace std;
53
OUTPUT :
Complexity :
Time Complexity : O(n3) .
EXPERIMENT : 12
AIM : WAP to implement Longest Common Sub – Sequence and analyze its complexity .
Compiler Requirement : Dev C++
Algorithm :
Define a DP Table dp[][]dp[][]dp[][]:
Recurrence Relation:
CODE :
#include <cstring>
#include <iostream>
using namespace std;
LCS_table[i][j] = 0;
else if (S1[i - 1] == S2[j - 1])
LCS_table[i][j] = LCS_table[i - 1][j - 1] + 1;
else
LCS_table[i][j] = max(LCS_table[i - 1][j], LCS_table[i][j - 1]);
}
}
int i = m, j = n;
while (i > 0 && j > 0) {
if (S1[i - 1] == S2[j - 1]) {
lcsAlgo[index - 1] = S1[i - 1];
i--;
j--;
index--;
}
else if (LCS_table[i - 1][j] > LCS_table[i][j - 1])
i--;
else
j--;
}
cout << "S1 : " << S1 << "\nS2 : " << S2 << "\nLCS: " << lcsAlgo << "\n";
}
int i, j;
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0)
L[i][j] = 0;
else if (S1[i - 1] == S2[j - 1])
L[i][j] = L[i - 1][j - 1] + 1;
else
L[i][j] = max(L[i - 1][j], L[i][j - 1]);
}
}
return L[m][n];
}
int main() {
char S1[] = "ACADB";
char S2[] = "CBDA";
int m = strlen(S1);
int n = strlen(S2);
OUTPUT :
Complexity :
Time Complexity : O(m*n) , where m & n are the lengths of the two strings .
Space Complexity : O(max(m,n)) , where m & n are the lengths of the two strings .
59
EXPERIMENT : 13
AIM : WAP to implement all pairs shortest path problem using Floyd’s Warshell algorithm. Parallelize
this algo, implement it and determine the speed-up achieved .
Compiler Requirement : Dev C++
Algorithm :
Initialize the solution matrix same as the input graph matrix as a first step.
Then update the solution matrix by considering all vertices as an intermediate
vertex.
The idea is to pick all vertices one by one and updates all shortest paths which include
the picked vertex as an intermediate vertex in the shortest path.
When we pick vertex number k as an intermediate vertex, we already have
considered vertices {0, 1, 2, .. k-1} as intermediate vertices.
For every pair (i, j) of the source and destination vertices respectively, there are two
possible cases.
k is not an intermediate vertex in shortest path from i to j. We keep the value
of dist[i][j] as it is.
k is an intermediate vertex in shortest path from i to j. We update the value
of dist[i][j] as dist[i][k] + dist[k][j], if dist[i][j] > dist[i][k] + dist[k][j]
CODE :
#include <bits/stdc++.h>
#include <omp.h> // Include OpenMP header for parallelization
using namespace std;
#define V 4
#define INF 99999
void printSolution(int dist[][V]);
void floydWarshall(int dist[][V]) {
int i, j, k;
for (k = 0; k < V; k++) {
#pragma omp parallel for private(i, j)
for (i = 0; i < V; i++) {
for (j = 0; j < V; j++) {
if (dist[i][j] > (dist[i][k] + dist[k][j]) && (dist[k][j] != INF &&
dist[i][k] != INF))
60
{ INF, INF, 0, 1 },
{ INF, INF, INF, 0 } };
OUTPUT :
Complexity :
Time Complexity : O(V3), where V is the number of vertices. This can be very slow for large graphs.
Space Complexity : O(V2) is manageable for graphs with a relatively small number of vertices.
However, for very large graphs, such as those with thousands or millions of vertices, the space
requirement can become a constraint due to memory limitations.
..
62
EXPERIMENT : 14 (a)
AIM : WAP to implement Naive String Matching algorithm and analyze its time and space complexity .
Compiler Requirement : Dev C++
Algorithm :
CODE :
#include <iostream>
#include <string>
int N = txt.size();
int j;
if (txt[i + j] != pat[j]) {
break;
}
}
if (j == M) {
int main() {
// Example 1
search(pat1, txt1);
// Example 2
cout<<"\n--------------------------------\n";
cout << "\nExample 2: \n\t\tagd\n\t\tg\n" << endl;
search(pat2, txt2);
64
return 0;
}
OUTPUT :
Complexity :
Time Complexity :
Worst-case: O((n−m+1)×m) – occurs when there are many repeated characters, causing maximum
checks at each step.
Best-case: O(n) – occurs when a match is found quickly or there are no matches.
Space Complexity : O(1) – no additional data structures are used other than loop counters and a few
auxiliary variables.
..
65
EXPERIMENT : 14 (b)
AIM : WAP to implement Rabin Karp algorithm and analyze its time and space complexity .
Compiler Requirement : Dev C++
Algorithm :
Let n be the length of text and m be the length of pattern.
Calculate the hash value of pattern (p) and the initial hash value of the first m
characters of text (t).
Loop through text from i = 0 to n - m:
If p == t, check each character of pattern with the corresponding substring in
text to confirm the match.
If confirmed, print i as the index where the pattern is found.
Calculate the hash value for the next window of text (t[i+1]) using the rolling hash
formula:
t[i+1] = (d * (t[i] - text[i] * h) + text[i + m]) % q
Where d is the number of characters in the input alphabet.
h is the value of d^(m-1) % q to shift the hash window.
Repeat until the end of text.
CODE :
#include <bits/stdc++.h>
using namespace std;
int main(){
char txt[] = "Legends spoke of a fearsome pirate known for his quick wit and
unmatched sword skills.The old captain warned the crew of the dangers of pirate-
infested waters.In his journal, the explorer recounted tales of pirate attacks and lost
treasures.";
char pat[] = "pirate";
int q = INT_MAX;
search(pat, txt, q);
return 0;
}
OUTPUT :
Complexity :
Time Complexity :
..
68
EXPERIMENT : 14 (c)
AIM : WAP to implement Knuth Morris Pratt algorithm and analyze its time and space complexity .
Compiler Requirement : Dev C++
Algorithm :
Preprocess the Pattern:
Create the LPS (Longest Prefix Suffix) array, which stores the lengths of the
longest proper prefixes of the pattern that are also suffixes for each position in
the pattern.
Initialize Indices:
Set two pointers: i for the text (initially 0) and j for the pattern (initially 0).
Search for the Pattern:
o Compare characters of the pattern and text using the indices:
If pattern[j] == text[i], increment both i and j.
If j equals the length of the pattern, a match is found at index i - j. Update
j using the LPS array.
Handle Mismatches:
o If a mismatch occurs:
If j is not 0, update j to lps[j - 1] to skip unnecessary comparisons.
If j is 0, simply increment i.
Continue Until End of Text:
Repeat the comparison until the end of the text is reached. Output the indices of
found matches.
CODE :
#include <iostream>
#include <string>
#include <vector>
using namespace std;
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
}
else {
if (len != 0) {
len = lps[len - 1];
}
else {
lps[i] = 0;
i++;
}
}
}
}
res.push_back(i - j);
j = lps[j - 1];
}
}
else {
if (j != 0)
j = lps[j - 1];
else
i++;
}
}
return res;
}
int main() {
return 0;
}
71
OUTPUT :
Complexity :
Time Complexity : O(n+m) , where (n) is the length of the target and (m) is the length of the search.
Space Complexity : O(m) because of the pre-processing involved, such as creating the pi table for
the pattern.
..
72
EXPERIMENT : 15
AIM : WAP to implement Sorting Network :
g(i,s) = min{Cik + g(k , S –{k})} .
Compiler Requirement : Dev C++
Algorithm :
Initialize:
o Let nnn be the number of elements to be sorted.
o Create a cost matrix CCC, where C[i][k]C[i][k]C[i][k] represents the cost of
comparing the ithi^{th}ith and kthk^{th}kth elements.
Recursive Function:
o Define a recursive function g(i,S)g(i, S)g(i,S) where SSS is the current set of
indices to sort. The function returns the minimum cost of sorting the elements
in SSS.
Base Case:
o If SSS has only one element, the cost is 000 because it's already sorted.
Recursive Case:
o For each element kkk in SSS, compute the cost of sorting the remaining
elements after comparing the ithi^{th}ith element with kkk and accumulate
the costs.
Memoization:
CODE :
#include <iostream>
#include <vector>
#include <limits.h>
#include <algorithm>
#include <unordered_map>
int main() {
int n;
cout << "Enter the number of elements: ";
cin >> n;
}
}
vector<int> S;
for (int i = 0; i < n; ++i) {
S.push_back(i);
}
cout << "Minimum cost to sort the elements: " << result << endl;
return 0;
}
OUTPUT :
Complexity :
Time Complexity : Worst-case: O(n⋅2n) in this case and generally it is : O(log n)
EXPERIMENT :
AIM : WAP to implement .
Compiler Requirement : Dev C++
Algorithm :
In .
M
CODE :
OUTPUT :
Complexity :
Time Complexity : hh
Space Complexity : hh
..
(2nd last kr 3rd last )