Download as pdf or txt
Download as pdf or txt
You are on page 1of 27

Page |3

Practical 1. Code and analyse to compute the greatest common divisor of two numbers.
#include<iostream>
using namespace std;
int GCD(int a,int b);
int count=1,temp;
int main(){
int a,b;
cout<<"enter the value of a ";
cin>>a;
cout<<"enter the value of b ";
cin>>b;
cout<<"GCD is "<<GCD(a,b);
return 0;
}
int GCD(int a,int b){
int min;
if(a==0 || b==0){
return 0;
}
else if(a>b){
min=b;
}
if(b>a){
min=b;
}
while(count<=min){
if(a%count==0 && b%count==0){
temp=count;
}
count++;
}
return temp;
}

Output
Page |4

Practical 2. Code and analyse to find the median element in an array of integers.
#include <iostream>
using namespace std; Output:
double findMedian(int a[], int n)
{
sort(a, a+n);
if (n % 2 != 0)
return (double)a[n/2];
else
return (double)(a[(n-1)/2] +
a[n/2])/2.0;
}
int main()
{
int a[] = { 1, 3, 4, 2, 7, 5, 8, 6 };
int n = sizeof(a)/sizeof(a[0]);
cout << "Median = " << findMedian(a, n) << endl;
return 0;
}

Practical 3. Code and analyse to find the majority element in an array of integers.
#include <iostream>
using namespace std;
void Majority(int arr[],int n)
{
int maxCount = 0;
int index = -1;
for(int i = 0; i < n; i++)
{
int count = 0;
for(int j = 0; j < n; j++)
{
if(arr[i] == arr[j])
count++; Output:
}
if(count > maxCount)
{
maxCount = count;
index = i;
}
}
if (maxCount > n/2)
cout << arr[index] << endl;

else
cout << "No Majority Element" << endl;
}
int main()
{
Page |5

int n,i,arr[i];
Output:
cout<<"Enter size of array: ";
cin>>n;
cout<<"Enter array to find Majority element: ";
for(i=0;i<n;i++)
{
cin>>arr[i];
}
cout<<"The Majority element is = ";
Majority(arr,n);
return 0;
}

Practical 4. Code and analyse to sort an array of integers using Heap sort.
#include <iostream>
using namespace std;
void getdata(int arr[],int size);
void heapify(int arr[], int n, int i)
{
int largest = i;
int l = 2*i + 1;
int r = 2*i + 2;
if (l < n && arr[l] > arr[largest])
largest = l;
if (r < n && arr[r] > arr[largest])
largest = r;
Heap sort is an in-place algorithm.
if (largest != i) Time complexity of heapify is O(Logn).
{ Time complexity of create Heap is O(n)
swap(arr[i], arr[largest]); Overall time complexity of Heap Sort is O(nLogn).
heapify(arr, n, largest);
}
}
void heapSort(int arr[], int n)
{
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
Output:
for (int i=n-1; i>=0; i--)
{
swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}
void printArray(int arr[], int n)
{
for (int i=0; i<n; ++i)
cout << arr[i] << " ";
cout << "\n";
}
Page |6

int main()
{ int n;
cout<<"enter no. of elements ";
cin>>n;
int arr[n];
getdata(arr,n);
heapSort(arr, n);
cout << "Sorted array is \n";
printArray(arr, n);
}
void getdata(int arr[],int size){
for(int i=0;i<size;i++){
cin>>arr[i];
}
}

Practical 5. Code and analyse to sort an array of integers using merge sort.
#include<stdlib.h>
#include<iostream>
using namespace std;
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
int L[n1], R[n2];
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
while (i < n1)
{
arr[k] = L[i];
i++;
k++; }
Page |7

while (j < n2)


{
arr[k] = R[j];
j++;
k++;
}
}
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
int m = l+(r-l)/2;
mergeSort(arr, l, m); Time complexity of Merge Sort is O(nLogn).
mergeSort(arr, m+1, r);
merge(arr, l, m, r); in all 3 cases (worst, average and best) as merge sort
always divides the array into two halves and take linear
} time to merge two halves.
}
void printArray(int A[], int size) Auxiliary Space: O(n)
Algorithmic Paradigm: Divide and Conquer
{
int i;
for (i=0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}
int main()
{
int arr[] = {12, 11, 13, 5, 6, 7};
int arr_size = sizeof(arr)/sizeof(arr[0]);
printf("Given array is \n");
printArray(arr, arr_size);
mergeSort(arr, 0, arr_size - 1);
printf("\nSorted array is \n");
printArray(arr, arr_size);
return 0;
}

Output
Page |8

Practical 6. Code and analyse to sort an array of integers using Quick sort.
#include <iostream>
using namespace std;
void swap(int* a, int* b)
{
int t = *a;
*a = *b;
*b = t;
}
int partition (int arr[], int low, int high)
{
int pivot = arr[high]; // pivot
int i = (low - 1); // Index of smaller element
for (int j = low; j <= high - 1; j++)
{
if (arr[j] < pivot)
{
i++; // increment index of smaller element
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
} Time Comlexity:
void quickSort(int arr[], int low, int high) Worst Case: O(n^2)
{ Average Case: O(nlogn)
Best Case: O(nlogn)
if (low < high)
{
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
} Output:
void printArray(int arr[], int size)
{
int i;
for (i = 0; i < size; i++)
cout << arr[i] << " ";
cout << endl;
}
int main()
{
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, n - 1);
cout << "Sorted array: \n";
printArray(arr, n);
return 0;
}
Page |9

Practical 7. Code and analyse the edit distance between two strings using dynamic programming.
#include<iostream>
using namespace std;
int min(int x, int y, int z)
{
return min(min(x, y), z);
}

int editDist(string str1 , string str2 , int m ,int n)


{
if (m == 0) return n;

if (n == 0) return m;
if (str1[m-1] == str2[n-1])
return editDist(str1, str2, m-1, n-1);
return 1 + min ( editDist(str1, str2, m, n-1),
editDist(str1, str2, m-1, n),
editDist(str1, str2, m-1, n-1) ); Time Complexity: O(m x n)
} Auxiliary Space: O(m x n)
int main()
{
string str1 = "sunday";
string str2 = "saturday";
cout << editDist( str1 , str2 , str1.length(), str2.length());

return 0;
}

Output:
P a g e | 10

Practical 8. Code and analyse to find an optimal solution to weighted interval scheduling using
dynamic programming.
#include <iostream>
using namespace std;
struct Job
{
int start, finish, profit;
};
bool jobComparataor(Job s1, Job s2)
{
return (s1.finish < s2.finish);
}
int latestNonConflict(Job arr[], int i)
{
for (int j=i-1; j>=0; j--)
{
if (arr[j].finish <= arr[i-1].start)
return j;
}
return -1;
}
int findMaxProfitRec(Job arr[], int n)
{
if (n == 1) return arr[n-1].profit;
int inclProf = arr[n-1].profit;
int i = latestNonConflict(arr, n);
if (i != -1)
inclProf += findMaxProfitRec(arr, i+1);
int exclProf = findMaxProfitRec(arr, n-1);

return max(inclProf, exclProf);


}
int findMaxProfit(Job arr[], int n)
{
sort(arr, arr+n, jobComparataor);

return findMaxProfitRec(arr, n);


} Time Complexity of the above Dynamic
int main() Programming Solution is O(n2). Note that the above
{ solution can be optimized to O(nLogn) using Binary
Search in latestNonConflict() instead of linear
Job arr[] = {{3, 10, 20}, {1, 2, 50}, {6, 19,
search.
100}, {2, 100, 200}};
int n = sizeof(arr)/sizeof(arr[0]);
cout << "The optimal profit is " <<
findMaxProfit(arr, n);
return 0;
}
P a g e | 11

Practical 9. Code and analyse to find an optimal solution to matrix chain multiplication using dynamic
programming.
#include<iostream>
using namespace std;
int MatrixChainOrder(int p[], int i, int j)
{
if(i == j)
return 0;
int k;
int min = INT_MAX;
int count;
for (k = i; k < j; k++)
{
count = MatrixChainOrder(p, i, k) +
MatrixChainOrder(p, k + 1, j) +
p[i - 1] * p[k] * p[j];

if (count < min)


min = count;
}
return min;
}

int main()
{ Time Complexity: O(n^3)
int arr[] = {1, 2, 3, 4, 3}; Auxiliary Space: O(n^2)
int n = sizeof(arr)/sizeof(arr[0]);

cout << "Minimum number of multiplications is "


<< MatrixChainOrder(arr, 1, n - 1);
}

Output
P a g e | 12

Practical 10.1. Code and analyse to do a depth-first search (DFS) on an undirected graph.
#include<iostream>
using namespace std;
int Arr[10][10],i,j,k,n,m,stack[10],top,v,visit[10],visited[10];
int main()
{
cout<<"Enter total no. of vertices: ";
cin>>n;
cout<<"Enter total no. of edges: ";
cin>>m;
cout<<"\nEnter Edges\n";
for(k=1;k<=m;k++)
{
cin>>i>>j;
Arr[i][j]=1;
}
cout<<"Enter initial vertex: ";
Time Complexity:
cin>>v;
O(V+E) where V is number of
cout<<"Depth first search order is: ";
cout<<v<<" "; vertices in the graph and E is
visited[v]=1; number of edges in the graph.
k=1;
while(k<n)
{
for(j=n;j>=1;j--)
if(Arr[v][j]!=0 && visited[j]!=1 && visit[j]!=1)
{
visit[j]=1;
stack[top]=j;
top++;
}
v=stack[--top];
cout<<v<<" ";
k++;
visit[v]=0;
visited[v]=1;
}
return 0;
}
P a g e | 13

Practical 10.2. Code and analyse to find the topological sort of a directed acyclic graph.
#include <iostream>
#include <list>
#include <stack>
using namespace std;
class Graph
{
int V;
list<int> *adj;
void topologicalSortUtil(int v, bool visited[], stack<int> &Stack);
public:
Graph(int V);
void addEdge(int v, int w);
void topologicalSort();
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w);
}
void Graph::topologicalSortUtil(int v, bool visited[], stack<int> &Stack)
{
visited[v] = true;
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
topologicalSortUtil(*i, visited, Stack);
Stack.push(v);
}
void Graph::topologicalSort()
{
stack<int> Stack;
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
for (int i = 0; i < V; i++)
if (visited[i] == false)
topologicalSortUtil(i, visited, Stack);
while (Stack.empty() == false)
{
cout << Stack.top() << " ";
Stack.pop();
}

}
P a g e | 14

int main() Output:


{
int n,v1,v2;
cin>>n;
Graph g(n);
for(int i=1;i<=n;i++)
{ cin>>v1>>v2;
g.addEdge(v1, v2);}
cout << " Topological Sort of the
given graph \n";
g.topologicalSort();

return 0;
}

Practical 10.3. Code and analyse to find a path from source to goal in a maze.
#include <iostream>
#define N 4
bool solveMazeUtil(int maze[N][N], int x, int y, int sol[N][N]);
void printSolution(int sol[N][N])
{ printf("path from source to goal can be found by fllowing 1's \n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
printf(" %d ", sol[i][j]);
printf("\n");
}
}
bool isSafe(int maze[N][N], int x, int y)
{
if (x >= 0 && x < N && y >= 0 && y < N && maze[x][y] == 1)
return true;

return false;
}
bool solveMaze(int maze[N][N])
{
int sol[N][N] = { { 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } };
if (solveMazeUtil(maze, 0, 0, sol) == false) {
printf("Solution doesn't exist");
return false;
}
printSolution(sol);
return true;
}
bool solveMazeUtil(int maze[N][N], int x, int y, int sol[N][N])
{
P a g e | 15

if (x == N - 1 && y == N - 1) {
sol[x][y] = 1;
return true;
}
if (isSafe(maze, x, y) == true) {
sol[x][y] = 1;
if (solveMazeUtil(maze, x + 1, y, sol) == true)
return true;
if (solveMazeUtil(maze, x, y + 1, sol) == true)
return true;
sol[x][y] = 0;
return false;
}
return false;
}
int main()
{
int maze[N][N] = { { 1, 0, 0, 0 },
{ 1, 1, 1, 1 },
{ 0, 0, 0, 1 },
{ 1, 1, 1, 1 } };

solveMaze(maze);
return 0;
}

Output:
P a g e | 16

Practical 11.1. Code and analyse to do a breadth-first search (BFS) on an undirected graph.
#include<iostream>
using namespace std;
int Arr[10][10],i,j,k,n,queue[10],front,rear,v,visit[10],visited[10];
int main()
{
int m;
cout<<"Enter no. of vertices: ";
cin>>n; Time Complexity:
cout<<"Enter no. of edges: ";
O(V+E) where V is number of vertices in the graph
cin>>m;
cout<<"\nEnter EDGES \n"; and E is number of edges in the graph.
for(k=1;k<=m;k++)
{
cin >>i>>j;
Arr[i][j]=1;
}
cout<<"Enter initial vertex: ";
cin>>v;
cout<<"Breadth first search order: \n";
cout<<v;
visited[v]=1;
k=1;
while(k<n)
{
for(j=1;j<=n;j++)
if(Arr[v][j]!=0 &&
visited[j]!=1 && visit[j]!=1)
{
visit[j]=1;

queue[rear++]=j;
}
v=queue[front++];
cout<<v<<" ";
k++;
visit[v]=0;
visited[v]=1;
}
return 0;
}

Practical 11.2. Code and analyse to find connected components of an undirected graph.
#include<iostream>
#include <list>
using namespace std;
class Graph
{
int V; // No. of vertices
list<int> *adj;
P a g e | 17

void DFSUtil(int v, bool visited[]);


public:
Graph(int V); // Constructor
void addEdge(int v, int w);
void connectedComponents();
};
void Graph::connectedComponents()
{
bool *visited = new bool[V];
for(int v = 0; v < V; v++)
visited[v] = false;
for (int v=0; v<V; v++)
{
if (visited[v] == false)
{ DFSUtil(v, visited);
cout << "\n"; }
}
}
void Graph::DFSUtil(int v, bool visited[])
{
visited[v] = true;
cout << v << " ";
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i)
if(!visited[*i])
DFSUtil(*i, visited);
}
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w) Output:
{
adj[v].push_back(w);
adj[w].push_back(v);
}

int main()
{

Graph g(5);
g.addEdge(1, 0);
g.addEdge(2, 3);
g.addEdge(3, 4);

cout << "Following are connected components \n";


g.connectedComponents();
return 0;
}
P a g e | 18

Practical 11.3. Code and analyse to check whether a given graph is bipartite.
#include <iostream>
#include <queue>
#define V 4
using namespace std;
bool isBipartite(int G[][V], int src)
{
int colorArr[V];
for (int i = 0; i < V; ++i)
colorArr[i] = -1;
colorArr[src] = 1;
queue <int> q;
q.push(src);
while (!q.empty())
{
int u = q.front();
q.pop();
if (G[u][u] == 1)
return false;
for (int v = 0; v < V; ++v)
{
if (G[u][v] && colorArr[v] == -1)
{
colorArr[v] = 1 - colorArr[u];
q.push(v);
}
else if (G[u][v] && colorArr[v] == colorArr[u])
return false;
}
}
return true;
}
int main()
{
int G[][V] = {{0, 1, 0, 1},
{1, 0, 1, 0}, Output:
{0, 1, 0, 1},
{1, 0, 1, 0}
};
isBipartite(G, 0) ? cout <<
"Yes" : cout << "No";
return 0;
}
P a g e | 19

Practical 12. Code and analyse to find shortest paths in a graph using Dijkstra’s algorithm.
#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 printSolution(int dist[])
{
printf("Vertex \t\t Distance from Source\n");
for (int i = 0; i < V; i++)
printf("%d \t\t %d\n", i, dist[i]);
}
Time Complexity of the implementation is O(V^2).
void dijkstra(int graph[V][V], int src) If the input graph is represented using adjacency
{ list, it can be reduced to O(E log V) with the help of
int dist[V]; binary heap.
bool sptSet[V];
for (int i = 0; i < V; i++)
dist[i] = INT_MAX, sptSet[i] = false;
dist[src] = 0;
for (int count = 0; count < V - 1; count++) {
int u = minDistance(dist, sptSet);
sptSet[u] = true;
for (int v = 0; v < V; v++)
if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX
&& dist[u] + graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
printSolution(dist); Output:
}
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 },
{ 8, 11, 0, 0, 0, 0, 1, 0, 7 },
{ 0, 0, 2, 0, 0, 0, 6, 7, 0 } };

dijkstra(graph, 0);
return 0;
}
P a g e | 20

Practical 13. Code and analyse to find shortest paths in a graph with arbitrary edge weights using
Bellman-Ford algorithm.
#include <iostream>
struct Edge {
int src, dest, weight;
};
struct Graph {
int V, E;
struct Edge* edge;
};
struct Graph* createGraph(int V, int E)
{
struct Graph* graph = new Graph;
graph->V = V;
graph->E = E;
graph->edge = new Edge[E];
return graph;
}
void printArr(int dist[], int n)
{
printf("Vertex Distance from Source\n");
for (int i = 0; i < n; ++i)
printf("%d \t\t %d\n", i, dist[i]);
}
void BellmanFord(struct Graph* graph, int src)
{
int V = graph->V;
int E = graph->E;
int dist[V];
for (int i = 0; i < V; i++)
dist[i] = INT_MAX;
dist[src] = 0;
for (int i = 1; i <= V - 1; i++) {
for (int j = 0; j < E; j++) {
int u = graph->edge[j].src;
int v = graph->edge[j].dest;
int weight = graph->edge[j].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v])
dist[v] = dist[u] + weight;
}
}
for (int i = 0; i < E; i++) {
int u = graph->edge[i].src;
int v = graph->edge[i].dest;
int weight = graph->edge[i].weight;
if (dist[u] != INT_MAX && dist[u] + weight < dist[v]) {
printf("Graph contains negative weight cycle");
return;
}
}
P a g e | 21

printArr(dist, V);
return;
}
int main()
{
int V = 5; // Number of vertices in graph
int E = 8; // Number of edges in graph
struct Graph* graph = createGraph(V, E);
graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = -1;
graph->edge[1].src = 0;
graph->edge[1].dest = 2;
graph->edge[1].weight = 4;
graph->edge[2].src = 1;
graph->edge[2].dest = 2;
graph->edge[2].weight = 3;
graph->edge[3].src = 1;
graph->edge[3].dest = 3;
graph->edge[3].weight = 2;
graph->edge[4].src = 1;
graph->edge[4].dest = 4;
graph->edge[4].weight = 2;
graph->edge[5].src = 3;
graph->edge[5].dest = 2;
graph->edge[5].weight = 5;
graph->edge[6].src = 3;
graph->edge[6].dest = 1;
graph->edge[6].weight = 1;
graph->edge[7].src = 4;
graph->edge[7].dest = 3;
graph->edge[7].weight = -3;

BellmanFord(graph, 0);
return 0;
}

Output:
P a g e | 22

Practical 14. Code and analyse to find the minimum spanning tree in a weighted, undirected graph.
#include <iostream>
using namespace std;
class Edge
{
public:
int src, dest, weight;
};
class Graph
{
public:
int V, E;
Edge* edge;
};
Graph* createGraph(int V, int E)
{
Graph* graph = new Graph;
graph->V = V;
graph->E = E;

graph->edge = new Edge[E];

return graph;
}
class subset
{
public:
int parent;
int rank;
};
int find(subset subsets[], int i)
{
if (subsets[i].parent != i)
subsets[i].parent = find(subsets, subsets[i].parent);

return subsets[i].parent;
}
void Union(subset subsets[], int x, int y)
{
int xroot = find(subsets, x);
int yroot = find(subsets, y);
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
P a g e | 23

}
int myComp(const void* a, const void* b)
{
Edge* a1 = (Edge*)a;
Edge* b1 = (Edge*)b;
return a1->weight > b1->weight;
}
void KruskalMST(Graph* graph)
{
int V = graph->V;
Edge result[V];
int e = 0;
int i = 0;
qsort(graph->edge, graph->E, sizeof(graph->edge[0]), myComp);
subset *subsets = new subset[( V * sizeof(subset) )];
for (int v = 0; v < V; ++v)
{
subsets[v].parent = v;
subsets[v].rank = 0;
}
while (e < V - 1 && i < graph->E)
{
Edge next_edge = graph->edge[i++];
int x = find(subsets, next_edge.src);
int y = find(subsets, next_edge.dest);
if (x != y)
{
result[e++] = next_edge;
Union(subsets, x, y);
}

}
cout<<"Following are the edges in the constructed MST\n";
for (i = 0; i < e; ++i)
cout<<result[i].src<<" -- "<<result[i].dest<<" == "<<result[i].weight<<endl;
return;
}
int main()
{
int V = 4; // Number of vertices in graph
int E = 5; // Number of edges in graph
Graph* graph = createGraph(V, E);

// add edge 0-1


graph->edge[0].src = 0;
graph->edge[0].dest = 1;
graph->edge[0].weight = 10;

// add edge 0-2


graph->edge[1].src = 0;
P a g e | 24

graph->edge[1].dest = 2;
graph->edge[1].weight = 6;

// add edge 0-3


graph->edge[2].src = 0;
graph->edge[2].dest = 3;
graph->edge[2].weight = 5;
Time Complexity:
// add edge 1-3
graph->edge[3].src = 1; O(ElogE) or O(ElogV).
graph->edge[3].dest = 3; Sorting of edges takes O(ELogE) time.
graph->edge[3].weight = 15; After sorting, we iterate through all edges and apply find-union
algorithm. The find and union operations can take atmost
// add edge 2-3
graph->edge[4].src = 2; O(LogV) time.
graph->edge[4].dest = 3; So overall complexity is O(ELogE + ELogV) time.
graph->edge[4].weight = 4;
The value of E can be atmost O(V2),

KruskalMST(graph); so O(LogV) are O(LogE) same.


Therefore, overall time complexity is O(ElogE) or O(ElogV)
return 0;
}

Output:
P a g e | 25

Practical 15. Code and analyse to find all occurrences of a pattern P in a given string S.
#include<iostream>
using namespace std;
int countFreq(string &pat, string &txt)
{
int M = pat.length();
int N = txt.length();
int res = 0;
for (int i = 0; i <= N - M; i++)
{
int j;
for (j = 0; j < M; j++)
if (txt[i+j] != pat[j])
break;
if (j == M)
{
res++;
j = 0;
}
}
return res;
}
int main()
{
string txt = "readmadglad";
string pat = "ad";
cout << countFreq(pat, txt);
return 0;
}

Output
P a g e | 26

Practical 16. Code and analyse to multiply two large integers using Karatsuba algorithm.
#include<iostream>
#include<stdio.h>
using namespace std;
int makeEqualLength(string &str1, string &str2)
{
int len1 = str1.size();
int len2 = str2.size();
if (len1 < len2)
{
for (int i = 0 ; i < len2 - len1 ; i++)
str1 = '0' + str1;
return len2;
}
else if (len1 > len2)
{
for (int i = 0 ; i < len1 - len2 ; i++)
str2 = '0' + str2;
}
return len1; // If len1 >= len2
}
string addBitStrings( string first, string second )
{
string result; // To store the sum bits
int length = makeEqualLength(first, second);
int carry = 0;
for (int i = length-1 ; i >= 0 ; i--)
{
int firstBit = first.at(i) - '0';
int secondBit = second.at(i) - '0';
int sum = (firstBit ^ secondBit ^ carry)+'0';

result = (char)sum + result;


carry = (firstBit&secondBit) | (secondBit&carry) | (firstBit&carry);
}
if (carry) result = '1' + result;

return result;
}
int multiplyiSingleBit(string a, string b)
{ return (a[0] - '0')*(b[0] - '0'); }

long int multiply(string X, string Y)


{
int n = makeEqualLength(X, Y);

// Base cases
if (n == 0) return 0;
if (n == 1) return multiplyiSingleBit(X, Y);
P a g e | 27

int fh = n/2; // First half of string, floor(n/2)


int sh = (n-fh); // Second half of string, ceil(n/2)

string Xl = X.substr(0, fh);


string Xr = X.substr(fh, sh);
string Yl = Y.substr(0, fh);
string Yr = Y.substr(fh, sh);
long int P1 = multiply(Xl, Yl);
long int P2 = multiply(Xr, Yr);
long int P3 = multiply(addBitStrings(Xl, Xr), addBitStrings(Yl, Yr));
return P1*(1<<(2*sh)) + (P3 - P1 - P2)*(1<<sh) + P2;
}
int main()
{
printf ("%ld\n", multiply("1100", "1010"));
Time Complexity: Time complexity of the above
printf ("%ld\n", multiply("110", "1010"));
solution is O(nlog23) = O(n1.59).
printf ("%ld\n", multiply("11", "1010"));
printf ("%ld\n", multiply("1", "1010")); Time complexity of multiplication can be further
printf ("%ld\n", multiply("0", "1010")); improved using another Divide and Conquer algorithm,
printf ("%ld\n", multiply("111", "111")); fast Fourier transform.
printf ("%ld\n", multiply("11", "11"));
}

Output:
P a g e | 28

Practical 17. Code and analyse to compute the convex hull of a set of points in the plane.
#include <iostream>
#include <stack>
#include <stdlib.h>
using namespace std;
struct Point
{
int x, y;
};
Point p0;
Point nextToTop(stack<Point> &S)
{
Point p = S.top();
S.pop();
Point res = S.top();
S.push(p);
return res;
}
int swap(Point &p1, Point &p2)
{
Point temp = p1;
p1 = p2;
p2 = temp;
}
int distSq(Point p1, Point p2)
{
return (p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y);
}
int orientation(Point p, Point q, Point r)
{
int val = (q.y - p.y) * (r.x - q.x) -
(q.x - p.x) * (r.y - q.y);
if (val == 0) return 0;
return (val > 0)? 1: 2;
}
int compare(const void *vp1, const void *vp2)
{
Point *p1 = (Point *)vp1;
Point *p2 = (Point *)vp2;
int o = orientation(p0, *p1, *p2);
if (o == 0)
return (distSq(p0, *p2) >= distSq(p0, *p1))? -1 : 1;

return (o == 2)? -1: 1;


}
void convexHull(Point points[], int n)
{
int ymin = points[0].y, min = 0;
P a g e | 29

for (int i = 1; i < n; i++) Time Complexity:


{
int y = points[i].y; For every point on the hull we examine all the
if ((y < ymin) || (ymin == y && other points to determine the next point. Time
points[i].x < points[min].x)) complexity is ?(m * n) where n is number of input
ymin = points[i].y, min = i; points and m is number of output or hull points (m
} <= n). In worst case, time complexity is O(n 2). The
swap(points[0], points[min]); worst case occurs when all the points are on the
p0 = points[0]; hull (m = n)
qsort(&points[1], n-1, sizeof(Point), compare);
int m = 1;
for (int i=1; i<n; i++)
{
while (i < n-1 && orientation(p0, points[i], points[i+1]) == 0)
i++;
points[m] = points[i];
m++;
}
if (m < 3) return;
stack<Point> S;
S.push(points[0]);
S.push(points[1]);
S.push(points[2]);
for (int i = 3; i < m; i++)
{
while (orientation(nextToTop(S), S.top(), points[i]) != 2)
S.pop();
S.push(points[i]);
}
while (!S.empty())
{
Point p = S.top();
cout << "(" << p.x << ", " << p.y <<")" << endl;
S.pop();
}
} Output:
int main()
{
Point points[] = {{0, 3}, {1,
1}, {2, 2}, {4, 4},
{0, 0}, {1, 2}, {3, 1},
{3, 3}};
int n =
sizeof(points)/sizeof(points[0]);
convexHull(points, n);
return 0;
}

You might also like