Daa Lab
Daa Lab
For
Academic Year (2023-24)
( 2100430100033)
1. Objective: To implement the Bubble, Insertion and Selection Sort and
analyze thetime complexity from its graph.
Bubble Sort
Code:
#include<bits/stdc++.h>
#include<ctime>
using namespace std;
int main(){
freopen("random.txt","r",stdin);
int
ran[]={10000,20000,30000,40000,80000,100000,120000,150000,180000,200000 }
; int ts[10];
for(int i=0;i<10;i++){
int n=ran[i];
int curr=time(NULL);
int arr[n];
for(int i=0;i<n;i++){
cin>>arr[i];
}
for(int i=0;i<n;i++){
for(int j=0;j<n-i-1;j++){
if(arr[j+1],arr[j])
swap(arr[j],arr[j+1]);
}
}
ts[i]=time(NULL)-curr;
cout<<ts[i]<<" ";
}
return 0;
}
Graph:
Bubble_Sort
1000
800
600
400
200
0
10000 20000 30000 40000 80000 100000 120000 150000 180000 200000
Selection Sort:
Code:
#include<bits/stdc++.h>
#include<ctime>
using namespace std;
int main(){
freopen("File2.txt","r",stdin);
int
ran[]={10000,20000,30000,40000,80000,100000,120000,150000,180000,200000 }
; int ts[10];
for(int i=0;i<10;i++){
int n=ran[i];
int curr=time(NULL);
int arr[n];
for(int i=0;i<n;i++){
cin>>arr[i];
}
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;
}
ts[i]=time(NULL)-curr;
cout<<ts[i]<<" ";
}
return 0;
}
SELECTION_SORT
700
600
500
400
300
200
100
0
10000 20000 30000 40000 80000 100000 120000 150000 180000 200000
Insertion Sort
#include <bits/stdc++.h>
#include <fstream>
#include <stdio.h> #include
<string> #include <time.h>
using namespace std;
int main(void)
{
clock_t start_b,end_b;
double t;
vector<int> a(100000);
int i = 0;
FILE *f;
if (f = fopen("random.txt", "r"))
{
}
return 0;
}
Graph
INSERTION SORT
200
150
100
50
0
10000 20000 30000 40000 50000 100000 120000 150000 180000 200000
2. Objective: To implement the Linear Search and Binary Search and find the
number ofcomparisons and analyze the time complexity from its graph.
Linear Search
#include <bits/stdc++.h>
#include <fstream>
#include <stdio.h> #include
<string> #include <time.h>
using namespace std; int
main(void)
{ clock_t start_b,end_b;
double t;
vector<int> a(100000);
int i = 0;
FILE *f;
if (f = fopen("file1.txt", "r"))
{
Graph
Binary Search
#include <bits/stdc++.h>
#include <fstream>
#include <stdio.h> #include
<string> #include <time.h>
using namespace std; int
main(void)
{
clock_t start_b,end_b;
double t;
vector<int> a(100000);
int i = 0;
FILE *f;
if (f = fopen("file1.txt", "r"))
{
while (fscanf(f, "%d", &a[i]) != EOF)
{
if(i>a.size())
break;
i++;
}
fclose(f);
for(int z=1;z<11;z++)
{
int x=1000;
int c=0;
int l=0,r=z*10000;
while (l <= r) {
int m = l + (r - l) / 2;
if (a[m] == x)
{ c+
+;
cout<<m<<endl;
}
if (a[m] < x)
{
l = m + 1;
c++;
}
else
{
r = m - 1;
c++;
}
}
cout<<c<<endl;
}
}
return 0;
}
Graph
BINARY SEARCH
18
16
14
12
10
8
6
4
2
0
50000 35000 20000 15000 10000 5000 4000 3000 2500 1000
Count Sort
#include <bits/stdc++.h>
#include <fstream>
#include <stdio.h> #include
<string> #include <time.h>
using namespace std;
void countingsort(vector<int>&vt,int n,int t)
{ long int arr[t+1];
long int c[n];
for(int i=0;i<=t;i++){
arr[i]=0;
}
for(int i=0;i<n;i++){
arr[vt[i]]++;
}
for(int i=1;i<=t;i++)
{ arr[i]=arr[i]+arr[i-
1];
}
for(int i=n-1;i>=0;i--){
c[--arr[vt[i]]]=vt[i];
}
}
int main(){
freopen("count.txt","r",stdin);
vector<int> vt1(100000); for(int
i=0;i<100000;i++){ cin>>vt1[i];
}
int
Range[10]={100000,90000,80000,70000,60000,50000,40000,30000,20000,10000};
for(int i=0;i<10;i++)
{ cloct_t start,end;
int tests=Range[i];
vector<int>vt=vt1;
start=clock();
countingsort(vt,tests-1,10);
end=clock();
double total_time=double(end-start)/CLOCTS_PER_SEC; cout<<"time
taken for "<<tests<<" inputs is : "<<total_time<<endl;
}
}
Radix Sort
#include <bits/stdc++.h>
#include <fstream>
#include <stdio.h> #include
<string> #include <time.h>
using namespace std;
void print(vector<string>& st, int n)
{
for (int i = 0; i < n; i++)
{ cout << st[i] << " ";
}
cout <<endl;
}
int char_at(string st, int k)
{
if (st.size() <= k)
return -1;
else
return st.at(k);
}
void radix sort(vector<string>& st, int lo, int hi, int k)
{
if (hi <= lo) {
return;
}
int count[256 + 2] = { 0 };
unordered_map<int, string> temp; for
(int i = lo; i <= hi; i++) {
int c = char_at(st[i], k);
count[c+2]++;
}
for (int r = 0; r < 256 + 1; r++)
count[r + 1] += count[r];
for (int i = lo; i <= hi; i++)
{ int c = char_at(st[i], k);
temp[count[c+1]++] = st[i];
}
for (int i = lo; i <= hi; i++)
st[i] = temp[i - lo];
for (int r = 0; r < 256; r++)
radixsort(st, lo + count[r], lo + count[r + 1] - 1,k + 1);
}
int main()
{
freopen("radix.txt","r",stdin);
vector<string> v1(100000);
for(int i=0;i<100000;i++)
cin>>v1[i];
int range[10]={1000,2000,3000,4000,5000,6000,7000,8000,9000,10000};
for(int i=0;i<10;i++)
{ clock_t ti,tf;
int inputs=range[i];
vector<string>v=v1;
v.resize(inputs); ti=clock();
radixsort(v,0,inputs-1,0);
tf=clock();
double tt=double(tf-ti)/CLOCKS_PER_SEC;
//print(v,inputs);
cout<<" "<<tt<<endl;
}
}
4. Objective: To implement the Heap Sort and analyze the time complexity
from its graph.
Heap Sort
#include <bits/stdc++.h>
#include <fstream>
#include <string> #include
<stdio.h>
using namespace std;
#include <time.h>
int l = 2 * i + 1;
int r = 2 * i + 2;
if (largest != i) { swap(arr[i],
arr[largest]);
heapify(arr, N, largest);
}
}
void heapSort(vector<int>arr, int N)
{
for (int i = N / 2 - 1; i >= 0; i–
heapify(arr, N, i);
swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
int main(void)
{
clock_t start, end; double
cpu_time_used;
vector<int>v(100000);
int i = 0;
FILE *file;
}
fclose(file);
int n=v.size();
int hold;
start = clock();
heapSort(v, n);
end = clock();
Merge Sort
#include <bits/stdc++.h>
#include <fstream>
#include <stdio.h>
using namespace std;
#include <time.h>
void merge(vector<int>a, int x, int b, int c) {
int n1 = b- x + 1;
int n2 = c-b;
int L[n1], M[n2];
for (int i = 0; i < n1; i++)
L[i] = a[l+ i];
for (int j = 0; j < n2; j++)
M[j] = a[b + 1 + j];
int i, j, k;
i = 0;
j = 0;
k = x;
while (i < n1 && j < n2)
{ if (L[i] <= M[j]) {
a[k] = L[i];
i++;
} else
{ a[k] =
M[j]; j++;
} k+
+;
}
while (i < n1) {
a[k] = L[i]; i+
+;
k++;
}
while (j < n2) {
a[k] = M[j]; j+
+;
k++;
}
}
void mergeSort(vector<int>a, int l, int r) { if
(l < r) {
int m = l + (r - l) / 2;
mergeSort(a, l, m);
mergeSort(a, m + 1, r);
merge(a, l, m, r);
}
}
int main(void)
{
clock_t start,end;
double t;
vector<int> v(10000);
int i = 0;
FILE *file;
if (file = fopen("random.txt", "r"))
{
int x;
while (fscanf(file, "%d", &v[i]) != EOF)
{
if(i>v.size())
break;
i++;
}
fclose(file);
int n=v.size();
start =clock();
mergeSort(v,0,n-1);
end=clock();
t=((double)(end-start))/CLOCKS_PER_SEC;
cout<<t;
}
return 0
;}
BEST CASE AVERAGE WORST C
CASE
Quick Sort
#include <bits/stdc++.h>
#include <fstream>
#include <stdio.h>
using namespace std;
#include <time.h>
void swap(int* x, int* y)
{ int t = *x;
*x = *y;
*y = t;
}
int partition(vector<int>a, int l, int h) { int
pivot = a[h];
int i= (l- 1);
for (int k = l; k <= h - 1; k++)
{ if (a[k] < pivot)
{ k++;
swap(&a[i], &a[k]);
}
}
swap(&a[i + 1], &a[h]);
return (i + 1);
}
void quickSort(vector<int>a, int l, int h) { if
(l < h) {
int p = partition(a, l, h);
quickSort(a, l, p - 1);
quickSort(a, p + 1, h);
}
}
int main()
{
clock_t start,end;
double t;
vector<int> vec(20000); int
i = 0;
FILE *file;
if (file = fopen("file1.txt", "r"))
{
int a;
while (fscanf(file, "%d", &vec[i]) != EOF)
{
if(i>vec.size())
break;
i++;
}
fclose(file);
int n=vec.size();
start =clock();
quickSort(vec,0,n-1);
end=clock();
t=((double)(end-start))/CLOCKS_PER_SEC;
cout<<t;
}
return 0;
}
BEST CASE AVERAGE WORST C
CASE
Theory : If n is odd then initialize min and max as the first element.
If n is even then initialize min and max as minimum and maximum of the first two elements respectively.
For the rest of the elements, pick them in pairs and compare their
maximum and minimum with max and min respectively
#include<bits/stdc++.h>
using namespace std;
struct Pair
{
int min;
int max;
};
i = 1;
}
while (i < n - 1)
{
if (arr[i] > arr[i + 1])
{
if(arr[i] > minmax.max)
minmax.max = arr[i];
if(arr[i + 1] < minmax.min) minmax.min
= arr[i + 1];
}
else
{
if (arr[i + 1] > minmax.max)
minmax.max = arr[i + 1];
Theory : Used Priority Queue, and inserted first K elements in the array. Then ,for remaining
,each time we compare it with the top element of the priority queue , if the top element is greater than the
current element then we pop front the priority queue and insert the current element into the priority
queue.
#include<bits/stdc++.h>
using namespace std;
int findKthMin(int arr[],int n,int k)
{
priority_queue<int>pq;
for(int i=0;i<k;i++)
{
pq.push(arr[i]);
}
int ans;
for(int i=k;i<n;i++)
{
if(arr[i]<pq.top())
{
pq.pop();
pq.push(arr[i]);
}
}
return pq.top();
}
int main()
{
int n;
cout<<"Enter the number of element : ";
cin>>n;
cout<<endl<<"Enter the elements : "; int
arr[n];
for(int i=0;i<n;i++)
{
cin>>arr[i];
}
int k;
cout<<"Enter the value of k : ";
cin>>k;
int res=findKthMin(arr,n,k);
cout<<"Kthe = "<<k<<" smallest element is : "<<res<<endl;
}
Objective : To implement the Prim’s Algorithm to find a Minimum Spanning Tree.
Theory : Prim's Algorithm converts it to a tree such that the sum of all edges of the tree is minimum.
Such a tree is called a Minimum Spanning Tree.
It "scs tkc gíccdQ appíoack to fi⭲d tkis mi⭲im"m spa⭲⭲i⭲g tícc.
#include<bits/stdc++.h>
#define V 6
parent[0] = -1;
value[0] = 0;
int main(){
int graph[V][V] = {
{0, 4, 6, 0, 8, 8},
{4, 0, 6, 3, 4, 8},
{6, 2, 0, 1, 8, 1},
{0, 3, 6, 0, 2, 2},
{0, 4, 4, 2, 0, 3},
{0, 0, 0, 3, 7, 4},
};
findMST(graph);
return 0;
}
Theory : Kruskal’s algorithm to find the minimum cost spanning tree uses the greedy approach. The
Greedy Choice is to pick the smallest weight edge that does not cause a cycle in the MST constructed so
far.
#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]=i;
rank[i]=0;
}
}
u=find(u);
v=find(v);
if(u!=v)
{
if(rank[u]<rank[v])
{
int temp=u;
u=v;
v=temp;
}
parent[v]=u;
if(rank[u]==rank[v])
rank[u]++;
}
}
};
class Edge{ public:
int u,v,weight;
int V, E; vector<Edge>
edges;
Graph(int v,int e){
V=v;
E=e;
}
static bool comparator(Edge e1, Edge e2)
{
return e1.weight < e2.weight;
}
void MST_Kruskal(){
int e=0,i=0,sum=0;
DSU dsu(V);
sort(edges.begin(), edges.end(), comparator);
while(e<V-1)
{
Edge edge=edges[i++];
int u=dsu.find(edge.u);
int v=dsu.find(edge.v);
if(u!=v)
{
cout<<"Adding edge "<<edge.u<<" <---> "<<edge.v<<" to MST\n";
sum+=edge.weight; dsu.Union(u,v);
e++;
}
}
Graph g(6,9);
g.addEdge(0,1,5);
g.addEdge(0,3,8);
g.addEdge(1,9,3);
g.addEdge(1,4,6);
g.addEdge(2,3,4);
g.addEdge(1,4,4);
g.addEdge(8,4,2);
g.addEdge(4,5,2);
g.addEdge(4,5,2);
g.MST_Kruskal();
return 0;
}
Theory : We will use almost the same approach as Recursive Implementation with the only change that,
we will maintain a 2-D array (say dp) of dimensions
n\times n
n×n all of whose entries initialized with -1 where dp[i][j] stores result for the sub-problem i..j. So for
calculating the answer for the sub-problem i..j firstly we will check if we already have calculated the
answer for it in past, by checking that if dp[i][j]!=-1. So if we already have calculated the answer for it
we need not solve it again instead, we can simply return dp[i][j].
#include<bits/stdc++.h>
using namespace std;
int **dp;
if(dp[low][high]!=-1)
return dp[low][high];
dp[low][high]=INT_MAX;
for(int k=low;k<high;k++){
int cost=MatrixChainMultiplication(mat, low, k)+
MatrixChainMultiplication(mat, k+1, high)+
mat[low-1]*mat[k]*mat[high];
if(cost<dp[low][high])
dp[low][high]=cost;
}
return dp[low][high];
}
int main(){
int mat[]={2, 4, 6, 8, 6};
int n=sizeof(mat)/sizeof(mat[0]);
dp=new int*[n];
for(int i=0;i<n;i++)
{ dp[i]=new int[n];
for(int j=0;j<n;j++)
dp[i][j]=-1;
}
cout<<"Minimum number of steps are : ";
cout<<MatrixChainMultiplication(mat, 1, n-1);
return 0;
}
Theory : The method of dynamic programming reduces the number of function calls. It stores the result
of each function call so that it can be used in future calls without the need for redundant calls.The time
taken by a dynamic approach is the time taken to fill the table (ie.
O(mn)).
#include <bits/stdc++.h>
using namespace std;
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--;
}
int main() {
char S1[] = "abcdabab";
char S2[] = "acdbcba"; int
m = strlen(S1);
int n = strlen(S2);
lcsAlgo(S1, S2, m, n);
}
Objective : To do the case study of P , NP , NP Complete , NP Hard Problem.
P Class
The P in the P class stands for Polynomial Time. It is the collection of decision problems(problems
with a “yes” or “no” answer) that can be solved by a deterministic machine in polynomial time.
Features:
1. The solution to P problems is easy to find.
2. P is often a class of computational problems that are solvable and tractable. Tractable means
that the problems can be solved in theory as well as in practice. But the problems that can be
solved in theory but not in practice are known as intractable.
NP Class
The NP in NP class stands for Non-deterministic Polynomial Time. It is the collection of decision
problems that can be solved by a non-deterministic machine in polynomial time.
Features:
1. The solutions of the NP class are hard to find since they are being solved by a non-
deterministic machine but the solutions are easy to verify.
2. Problems of NP can be verified by a Turing machine in polynomial time.
This class contains many problems that one would like to be able to solve effectively:
An NP-hard problem is at least as hard as the hardest problem in NP and it is the class of the problems
such that every problem in NP reduces to NP-hard.
Features:
1. Halting problem.
2. Qualified Boolean formulas.
3. No Hamiltonian cycle.
NP-complete class
A problem is NP-complete if it is both NP and NP-hard. NP-complete problems are the hard problems in
NP.
Features: