You are on page 1of 13

DIGITAL ASSIGNMENT - 1

NAME: M BHANU PRAKASH


REG NUMBER: 19MID0088

DATE: 31-03-2021

ADVANCED ALGORITHMS SLOT: G1

1. Write a program to find the shortest path in a graph using either


Prim’s Algorithm or Kruskal’s Algorithm.

#include <bits/stdc++.h>
using namespace std;
#define V 5
int minKey(int key[], bool mstSet[])
{

int min = INT_MAX, min_index;


for (int v = 0; v < V; v++)
if (mstSet[v] == false && key[v] < min)
min = key[v], min_index = v;

return min_index;
}

void printMST(int parent[], int graph[V][V])


{
cout<<"Edge \tWeight\n";
for (int i = 1; i < V; i++)
cout<<parent[i]<<" - "<<i<<" \t"<<graph[i][parent[i]]<<" \n";
}

void primMST(int graph[V][V])


{
int parent[V];
int key[V];
bool mstSet[V];

for (int i = 0; i < V; i++)


key[i] = INT_MAX, mstSet[i] = false;
key[0] = 0;
parent[0] = -1;

for (int count = 0; count < V - 1; count++)


{

int u = minKey(key, mstSet);


mstSet[u] = true;
for (int v = 0; v < V; v++)
if (graph[u][v] && mstSet[v] == false && graph[u][v] < key[v])
parent[v] = u, key[v] = graph[u][v];
}

printMST(parent, graph);
}

int main()
{
int graph[V][V] = { { 0, 2, 0, 6, 0 },
{ 2, 0, 3, 8, 5 },
{ 0, 3, 0, 0, 7 },
{ 6, 8, 0, 0, 9 },
{ 0, 5, 7, 9, 0 } };

primMST(graph);
return 0;
}
2. Write a program to create a binary search tree. Provide facilities to
insert, delete, update and search nodes in the tree.

#include<stdio.h>
#include<stdlib.h>
struct node
{
int info;
struct node*left;
struct node*right;
};
typedef struct node BST;
BST *LOC, *PAR;
void search(BST *root, int item)
{
BST *save,*ptr;
if (root == NULL)
{
LOC = NULL;
PAR=NULL;
}
if (item == root -> info)
{
LOC = root;
PAR = NULL;
return;
}
if (item < root->info)
{
save = root;
ptr = root->left;
}
else
{
save = root;
ptr = root -> right;
}
while( ptr != NULL)
{
if (ptr -> info == item)
{
LOC = ptr;
PAR = save;
return;
}
if(item < ptr->info)
{
save = ptr;
ptr = ptr->left;
}
else
{
save = ptr;
ptr = ptr->right;
}
}
LOC = NULL;
PAR = save;
return;
}
struct node* findmin(struct node*r)
{
if (r == NULL)
return NULL;
else if (r->left!=NULL)
return findmin(r->left);
else if (r->left == NULL)
return r;
}
struct node*insert(struct node*r, int x)
{
if (r == NULL)
{
r = (struct node*)malloc(sizeof(struct node));
r->info = x;
r->left = r->right = NULL;
return r;
}
else if (x < r->info)
r->left = insert(r->left, x);
else if (x > r->info)
r->right = insert(r->right, x);
return r;
}
struct node* del(struct node*r, int x)
{
struct node *t;
if(r == NULL)
printf("\nElement not found");
else if (x < r->info)
r->left = del(r->left, x);
else if (x > r->info)
r->right = del(r->right, x);
else if ((r->left != NULL) && (r->right != NULL))
{
t = findmin(r->right);
r->info = t->info;
r->right = del(r->right, r->info);
}
else
{
t = r;
if (r->left == NULL)
r = r->right;
else if (r->right == NULL)
r = r->left;
free(t);
}
return r;
}
int main()
{
struct node* root = NULL;
int x, c = 1, z;
int element;
char ch;
printf("\nEnter an element: ");
scanf("%d", &x);
root = insert(root, x);
printf("\nDo you want to enter another element :y or n");
scanf(" %c",&ch);
while (ch == 'y')
{
printf("\nEnter an element:");
scanf("%d", &x);
root = insert(root,x);
printf("\nPress y or n to insert another element: y or n: ");
scanf(" %c", &ch);
}
while(1)
{
printf("\n1 Insert an element ");
printf("\n2 Delete an element");
printf("\n3 Search for an element ");
printf("\n4 Exit ");
printf("\nEnter your choice: ");
scanf("%d", &c);
switch(c)
{
case 1:
printf("\nEnter the item:");
scanf("%d", &z);
root = insert(root,z);
break;
case 2:
printf("\nEnter the info to be deleted:");
scanf("%d", &z);
root = del(root, z);
break;
case 3:
printf("\nEnter element to be searched: ");
scanf("%d", &element);
search(root, element);
if(LOC != NULL)
printf("\n%d Found in Binary Search Tree !!\n",element);
else
printf("\nIt is not present in Binary Search Tree\n");
break;
case 4:
printf("\nExiting...");
return;
default:
printf("Enter a valid choice: ");
}
}
return 0;
}
3. Write algorithms to implement
A) Depth First Search Algorithm
o Step 1: SET STATUS = 1 (ready state) for each node in G
o Step 2: Push the starting node A on the stack and set its STATUS = 2
(waiting state)
o Step 3: Repeat Steps 4 and 5 until STACK is empty
o Step 4: Pop the top node N. Process it and set its STATUS = 3 (processed
state)
o Step 5: Push on the stack all the neighbours of N that are in the ready
state (whose STATUS = 1) and set their
STATUS = 2 (waiting state)
[END OF LOOP]
o Step 6: EXIT

B) Breadth First Search Algorithm

o Step 1: SET STATUS = 1 (ready state)


for each node in G
o Step 2: Enqueue the starting node A
and set its STATUS = 2
(waiting state)
o Step 3: Repeat Steps 4 and 5 until
QUEUE is empty
o Step 4: Dequeue a node N. Process it
and set its STATUS = 3
(processed state).
o Step 5: Enqueue all the neighbours of
N that are in the ready state
(whose STATUS = 1) and set
their STATUS = 2
(waiting state)
[END OF LOOP]
o Step 6: EXIT

4. Compare Ford-Fulkerson Method and Edmonds-Karp algorithm and


explain them.
It's possible to show that no modification to the residual graph ever reduces
the distance from the source to any vertex; with this, and the fact that BFS
always finds a shortest path, it's possible to show that after finding at most
|V||E||V||E| augmenting paths, no source-tosink path remains in the residual
graph. The distance from the source to all other nodes is always increasing, it
in fact means (or should mean) that this never decreases -- that is, the
distance from the source to a particular node can stay the same after an
augmentation, or it can be larger, but it can never be smaller. This is the
difference between Ford-Fulkerson Method and EdmondsKarp algorithm
Edmonds-Karp is a specialisation/elaboration of Ford-Fulkerson, so any
bound for the latter also applies to the former. In other words, Edmonds-Karp
is O(|E|min(fmax,|V||E|)) O(|E|min(fmax,|V||E|)) time (and writing it this way
does add information, since fmaxfmax can be much smaller than |V||E||V||E| )
This is the only time when you might otherwise consider using some other
variant of FordFulkerson in preference to EdmondsKarp. The above does not
imply that Edmonds-Karp is faster than a particular (say, DFS-based) variant
of Ford-Fulkerson on any particular instance.
Ford–Fulkerson algorithm isn't guaranteed to terminate, it may run forever in
certain cases and it's runtime(Complexity) is also depended on the max flow
O(ME) where M is the Max flow. Edmonds Karp algorithm guarantees
termination and removes the max flow dependency O(VE2).
Ford-Fulkerson is a Method and Edmonds-Karp is a algorithm BFS and DFS
have the same runtime, but DFS only promises to find a path from source to
sink in the residual graph -- not necessarily a shortest possible such path,
which BFS does promise. It's possible to show that no modification to the
residual graph ever reduces the distance from the source to any vertex; with
this, and the fact that BFS always finds a shortest path, it's possible to show
that after finding at most |V||E||V||E| augmenting paths, no source-tosink path
remains in the residual graph. The distance from the source to all other nodes
is always increasing, it in fact means (or should mean) that this never
decreases -- that is, the distance from the source to a particular node can stay
the same after an augmentation, or it can be larger, but it can never be
smaller. This is the difference between Ford-Fulkerson Method and Edmonds-
Karp algorithm.

Ford-Fulkerson method:
Let's define one more thing. A residual capacity of an directed edge is the capacity
minus the flow. It should be noted that if there is a flow along some directed
edge (u,v)(u,v), than the reversed edge has capacity 0 and we can define the flow
of it as f((v,u))=−f((u,v))f((v,u))=−f((u,v)). This also defines the residual capacity
for all reversed edges. From all these edges we can create a residual network,
which is just a network with the same vertices and same edges, but we use the
residual capacities as capacities.

The Ford-Fulkerson method works as follows. First we set the flow of each edge to
zero. Then we look for an augmenting path from ss to tt. An augmenting path is
simple path in the residual graph, i.e. along the edges whose residual capacity is
positive. Is such a path is found, then we can add increase the flow along these
edges. We keep on searching for augmenting paths and increasing the flow. Once
there doesn't exists an augmenting path any more, the flow is maximal.

Let us specify in more detail, what increasing the flow along an augmenting path
means. Let CC be the smallest residual capacity of the edges in the path. Then we
increase the flow in the following way: we
update f((u,v)) += Cf((u,v)) += C and f((v,u)) -= Cf((v,u)) -= C for every
edge (u,v)(u,v) in the path.

Edmonds-Karp algorithm:
Edmonds-Karp algorithm is just an implementation of the Ford-Fulkerson method
that uses BFS for finding augmenting paths. The algorithm was first published by
Yefim Dinitz in 1970, and later independently published by Jack Edmonds and
Richard Karp in 1972.

The complexity can be given independently of the maximal flow. The algorithm runs
in O(VE2)O(VE2) time, even for irrational capacities. The intuition is, that every time
we find an augmenting path one of the edges becomes saturated, and the distance
from the edge to ss will be longer, if it appears later again in an augmenting path.
And the length of a simple paths is bounded by VV.

NAME: M BHANU PRAKASH


REG NUMBER: 19MID0088

You might also like