Top Banner
NIE Institute of Technology Department of Computer Science & Engg And Department of Information science & Engg ALGORITHMS LABORATORY MANUAL For 5 th SEM CSE & ISE Sub Code: 06CSL58 Introduction Analysis of algorithms Analysis is one of the important step in problem solving. Here we estimate time and space for a given problem. Once we have these estimations, select an algorithm which is more efficient in terms of time and space. Time Efficiency: Indicates how fast the algorithm runs. Space Efficiency: Indicates how much extra memory is required for the algorithm .
42

NIEIT ada lab manual (1)

Apr 03, 2015

Download

Documents

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: NIEIT ada lab manual (1)

NIE Institute of Technology

Department of Computer Science & EnggAnd

Department of Information science & Engg

ALGORITHMS LABORATORY MANUALFor 5th SEM CSE & ISESub Code: 06CSL58

Introduction

Analysis of algorithms

Analysis is one of the important step in problem solving. Here we estimate time and

space for a given problem. Once we have these estimations, select an algorithm which is more

efficient in terms of time and space.

Time Efficiency: Indicates how fast the algorithm runs.

Space Efficiency: Indicates how much extra memory is required for the algorithm .

The most important characteristics of any algorithm are it’s simplicity and generality.

Simplicity: Simple algorithms are easy to understand, debug and easy to program.

Page 2: NIEIT ada lab manual (1)

Generality: It should be a generic solution to the given problem.

Design an algorithm

After the problem is clearly stated and the type of algorithm and data structure are

selected, the solution to solve the problem should be specified. One or more algorithms may be

correct to solve a given problem. But effectiveness may be different from solution to solution.

Algorithm

An algorithm is a technique to solve a problem systematically. It takes a set of input and

produces a desired output. Now algorithm can be defined as an unambiguous an ordered

sequence of steps that are carried to get a solution to a problem. Pictorial representation of an

algorithm is as shown below .

Notion of an algorithm

Linear Search

In computer science, linear search is a search algorithm, also known as sequential

search, that is suitable for searching a list of data for a particular value.

It operates by checking every element of a list one at a time in sequence until a match is

found. Linear search runs in O(n). If the data are distributed randomly, the expected number of

comparisons that will be necessary is: where n is the number of elements in the list and k is the

number of times that the value being searched for appears in the list. The best case is that the

value is equal to the first element tested, in which case only 1 comparison is needed. The worst

case is that the value is not in the list (or it appears only once at the end of the list), in which case

n comparisons are needed.

The simplicity of the linear search means that if just a few elements are to be searched it

is less trouble than more complex methods that require preparation such as sorting the list to be

searched or more complex data structures, especially when entries may be subject to frequent

revision. Another possibility is when certain values are much more likely to be searched for than

Page 3: NIEIT ada lab manual (1)

others and it can be arranged that such values will be amongst the first considered in the list.

The following pseudo code describes the linear search technique.

For each item in the list:

Check to see if the item you're looking for matches the item in the list.

If it matches.

Return the location where you found it (the index).

If it does not match.

Continue searching until you reach the end of the list.

If we get here, we know the item does not exist in the list. Return -1.

Binary Search Algorithm (or binary chop)

Binary search is a technique for locating a particular value in a sorted list. The method

makes progressively better guesses, and closes in on the location of the sought value by selecting

the middle element in the span (which, because the list is in sorted order, is the median value),

comparing its value to the target value, and determining if it is greater than, less than, or equal to

the target value. A guessed index whose value turns out to be too high becomes the new upper

bound of the span, and if its value is too low that index becomes the new lower bound. A binary

search is an example of a divide and conquer search algorithm.

The following pseudo code describes the Binary search technique

BinarySearch(A[0..N-1], value, low, high)

{

if (high < low)

return -1 // not found

mid = low + ((high - low) / 2) // Note: not (low + high) / 2 !!

if (A[mid] > value)

Page 4: NIEIT ada lab manual (1)

return BinarySearch(A, value, low, mid-1)

else if (A[mid] < value)

return BinarySearch(A, value, mid+1, high)

else

return mid // found

}

• Implement Recursive Binary search and Linear search and determine the time required to search an element. Repeat the experiment for different values of n, the number of elements in the list to be searched and plot a graph of the time taken versus n.

Page 5: NIEIT ada lab manual (1)

Heap Sort

Heapsort (method) is a comparison-based sorting algorithm, and is part of the selection

sort family. The heap sort works as its name suggests - it begins by building a heap out of the

data set, and then removing the largest item and placing it at the end of the sorted array. After

removing the largest item, it reconstructs the heap and removes the largest remaining item and

places it in the next open position from the end of the sorted array. This is repeated until there are

no items left in the heap and the sorted array is full. Elementary implementations require two

arrays - one to hold the heap and the other to hold the sorted elements.

Heapsort uses two heap operations: insertion and root deletion. Each extraction places an

element in the last empty location of the array. The remaining prefix of the array stores the

unsorted elements.

• Sort a given set of elements using the Heap sort method and determine the time required to sort the elements. Repeat the experiment for different values of n, the number of elements in the list to be sorted and plot a graph of the time taken versus n.

#include<iostream.h>#include<conio.h>//#define MTIMES 100//#define NTIMES 10000#include<time.h>#include<dos.h>#include<stdlib.h>int i,n,a[25000],j;

class heap{

public: void heapify(int a[], int n);void heapsort(int a[],int n);

};

void heap::heapify(int a[],int n){

int i,j,v,heap,k;for(i=n/2;i>0;i--){

k=i;v=a[i];

Page 6: NIEIT ada lab manual (1)

heap=0;while(!heap&&(2*k)<=n){

j=2*k;if(j<n){

if(a[j]<a[j+1]){

j=j+1;}

}if(v>=a[j])

heap=1;else{

a[k]=a[j];k=j;

}}a[k]=v;

}}

void heap::heapsort(int a[],int n){

int temp,i,j; heapify(a,n); for(i=1;i<=n;i++) {

for(j=i+1;j<=n;j++){

if(a[i]>a[j]){

temp=a[i];a[i]=a[j];a[j]=temp;

}}

}}

void main(){

clock_t st, et;heap h;clrscr();cout<<"Enter the value of N:\n"<<endl;cin>>n;cout<<"Enter the array element:\n"<<endl;for(i=1;i<=n;i++)//cin>>a[i];a[i]=rand()%100;

Page 7: NIEIT ada lab manual (1)

cout<<"The array element genearted are:\n"<<endl;for(i=1;i<=n;i++)cout<<"\t"<<a[i];

st=clock(); // for(i=0;i<MTIMES;i++) //for(j=0;j<NTIMES;j++) h.heapsort(a,n);et=clock();

cout<<"\nThe sorted elements are:\n"<<endl;for(i=1;i<=n;i++)cout<<"\t"<<a[i];

cout<<"\nBegin time="<<st<<endl;cout<<"End time="<<et<<endl;cout<<"Total number of clock ticks="<<(et-st)<<endl;cout<<"Total time required="<<(et-st)/CLK_TCK<<endl;

getch();}

Merge sort

Merge sort is an O(n log n) comparison-based sorting algorithm. In most implementations it is

stable, meaning that it preserves the input order of equal elements in the sorted output. It is an

example of the divide and conquer algorithmic paradigm. It was invented by John von Neumann

in 1945.

Conceptually, a merge sort works as follows:

• If the list is of length 0 or 1, then it is already sorted. Otherwise:

• Divide the unsorted list into two sublists of about half the size.

• Sort each sublist recursively by re-applying merge sort.

• Merge the two sublists back into one sorted list.

Merge sort incorporates two main ideas to improve its runtime:

• A small list will take fewer steps to sort than a large list.

• Fewer steps are required to construct a sorted list from two sorted lists than two unsorted

lists. For example, you only have to traverse each list once if they're already sorted (see

the merge function below for an example implementation).

Example: Using merge sort to sort a list of integers contained in an array:

Page 8: NIEIT ada lab manual (1)

Suppose we have an array A with n indices ranging from A0 to An − 1. We apply merge sort to

A(A0..Ac − 1) and A(Ac..An − 1) where c is the integer part of n / 2. When the two halves are

returned they will have been sorted. They can now be merged together to form a sorted array.

• Sort a given set of elements using Merge sort method and determine the time required to sort the elements. Repeat the experiment for different values of n, the number of elements in the list to be sorted and plot a graph of the time taken versus n.

#include<iostream.h>#include<conio.h>#include<dos.h>#include<time.h>int a[1000],b[1000],c[1000],i,n;

class msort{

public: void merge(int,int,int);void mergesort(int,int);

};

void msort::merge(int l,int h,int mid){

int i=l,j=mid+1,k=l;while(i<=mid && j<=h){

if(a[i]<a[j])c[k++]=a[i++];elsec[k++]=a[j++];

}while(i<=mid)c[k++]=a[i++];while(j<=h)c[k++]=a[j++];for(i=l;i<k;i++)a[i]=c[i];

}

void msort::mergesort(int l,int h){

int mid;if(l<h){

mid=(l+h)/2;delay(100);mergesort(l,mid);mergesort(mid+1,h);merge(l,h,mid);

}}

Page 9: NIEIT ada lab manual (1)

void main(){

clock_t st,et;

msort m;clrscr();

cout<<"Enter the value of n"<<endl;cin>>n;cout<<"Enter the elements"<<endl;

for(i=0;i<n;i++)cin>>a[i];

st=clock();m.mergesort(0,n-1);et=clock();

cout<<"\nThe sorted array is"<<endl;for(i=0;i<n;i++)cout<<"\t"<<a[i];

cout<<"\nBegin time="<<st<<endl;cout<<"End time="<<et<<endl;cout<<"Total number of clock ticks="<<(et-st)<<endl;cout<<"Total time required="<<(et-st)/CLK_TCK<<endl;

getch();}

Selection sort

Selection sort is a sorting algorithm, specifically an in-place comparison sort. It has O(n2)

complexity, making it inefficient on large lists, and generally performs worse than the similar

insertion sort. Selection sort is noted for its simplicity, and also has performance advantages over

more complicated algorithms in certain situations.

The algorithm works as follows:

• Find the minimum value in the list

• Swap it with the value in the first position

• Repeat the steps above for the remainder of the list (starting at the second position and

advancing each time)

Effectively, we divide the list into two parts: the sublist of items already sorted, which we build

up from left to right and is found at the beginning, and the sublist of items remaining to be

sorted, occupying the remainder of the array.

Page 10: NIEIT ada lab manual (1)

• a Sort a given set of elements using Selection sort and determine the time required to sort elements. Repeat the experiment for different values of n, the number of elements in the list to be sorted and plot a graph of the time taken versus n.

#include<iostream.h>#include<conio.h>#include<dos.h>#include<time.h>#include<stdlib.h>

int a[16000],i,n,j,min,t;

class selsort{

public: void selection(int);};

void selsort:: selection(int n) {

for(i=0;i<n-1;i++){

min=i;

for(j=i+1;j<n;j++){

if(a[j]<a[min])min=j;

}t=a[i];a[i]=a[min];a[min]=t;}

}

void main(){

clock_t st,et;selsort s;clrscr();

cout<<"Enter the value of n"<<endl;cin>>n;cout<<"The elements generated are"<<endl;

for(i=0;i<n;i++)a[i]=rand()%100;

for(i=0;i<n;i++)cout<<"\t"<<a[i];

st=clock();s.selection(n);et=clock();

Page 11: NIEIT ada lab manual (1)

cout<<"\nThe sorted array is"<<endl;for(i=0;i<n;i++)cout<<"\t"<<a[i];

cout<<"\nBegin time="<<st<<endl;cout<<"End time="<<et<<endl;cout<<"Total number of clock ticks="<<(et-st)<<endl;cout<<"Total time required="<<(et-st)/CLK_TCK<<endl;

getch();}

The knapsack problem or rucksack problem

The knap sack problem is a problem in combinatorial optimization: Given a set of items,

each with a weight and a value, determine the number of each item to include in a collection so

that the total weight is less than a given limit and the total value is as large as possible. It derives

its name from the problem faced by someone who is constrained by a fixed-size knapsack and

must fill it with the most useful items.

The problem often arises in resource allocation with financial constraints. A similar

problem also appears in combinatorics, complexity theory, cryptography and applied

mathematics.

0-1 knapsack problem

A dynamic programming solution for the 0-1 knapsack problem also runs in pseudo-

polynomial time. Assume w1, ..., wn, W are strictly positive integers. Define A(j, Y) to be the

maximum value that can be attained with weight less than or equal to Y using items up to j.

We can define A(j,Y) recursively as follows:

• A(0, Y) = 0

• A(j, 0) = 0

• A(j, Y) = A(j − 1, Y)  if wj > Y

• A(j, Y) = max { A(j − 1, Y),  pj + A(j − 1, Y − wj) }  if wj ≤ Y.

The solution can then be found by calculating A(n, W). To do this efficiently we can use a table

to store previous computations. This solution will therefore run in O(nW) time and O(nW) space,

though with some slight modifications we can reduce the space complexity to O(W).

• Implement 0/1 Knapsack problem using dynamic programming

Page 12: NIEIT ada lab manual (1)

#include<iostream.h>#include<conio.h>

int n,m,i,j,a,b,w[10],v[10][10],p[10];

class knap{

public: int max(int a,int b);void ksack(int n,int w[],int m,int v[][10],int p[]);void optsol(int n,int m,int w[],int v[10][10]);

};

int knap::max(int a,int b){

return a>b?a:b;}

void knap::ksack(int n,int w[],int m,int v[][10],int p[]){

int i,j;for(i=0;i<=n;i++)

{ for(j=0;j<=m;j++) { if(i==0||j==0)

v[i][j]=0; else if(j<w[i])

v[i][j]=v[i-1][j]; else

v[i][j]=max(v[i-1][j],v[i-1][j-w[i]]+p[i]); }

}}void knap::optsol(int n,int m,int w[],int v[10][10]){

int i,j,x[10];

cout<<"\nThe optimal solution is"<<v[n][m]<<endl;for(i=0;i<n;i++)

x[i]=0;

i=n; j=m;while(i!=0 && j!=0){

if(v[i][j]!=v[i-1][j]){

x[i]=1;j=j-w[i];

}i=i-1;

}cout<<"\nThe Object Selected is:\n";

Page 13: NIEIT ada lab manual (1)

for(i=1;i<=n;i++){

cout<<"X["<<i<<"]"<<"\t";}cout<<"=";

for(i=1;i<=n;i++){

cout<<x[i];}

}

void main(){

knap k;clrscr();cout<<"Enter the number of objects\n";cin>>n;cout<<"\nEnter the weights of n objects\n";for(i=1;i<=n;i++)

cin>>w[i];cout<<"\nEnter the profits of n objects\n";for(i=1;i<=n;i++)

cin>>p[i];cout<<"\nEnter the capacity of knapsack\n";cin>>m;k.ksack(n,w,m,v,p);k.optsol(n,m,w,v);

getch();}

Dijkstra's algorithm,

Dijkstra’s algorithm conceived by Dutch computer scientist Edsger Dijkstra in 1959 is a

graph search algorithm that solves the single-source shortest path problem for a graph with

nonnegative edge path costs, producing a shortest path tree. This algorithm is often used in

routing.

For a given source vertex (node) in the graph, the algorithm finds the path with lowest

cost (i.e. the shortest path) between that vertex and every other vertex. It can also be used for

finding costs of shortest paths from a single vertex to a single destination vertex by stopping the

algorithm once the shortest path to the destination vertex has been determined. For example, if

the vertices of the graph represent cities and edge path costs represent driving distances between

pairs of cities connected by a direct road, Dijkstra's algorithm can be used to find the shortest

route between one city and all other cities. As a result, the shortest path first is widely used in

network routing protocols, most notably (Intermediate system to intermediate system (IS-IS),

and OSPF (Open Shortest Path First).

Page 14: NIEIT ada lab manual (1)

• From a given vertex in a weighted connected graph, find shortest

paths to other vertices using Dijkstra's algorithm

#include<iostream.h>#include<conio.h>

int i,j,count=1,source,curr,cost[10][10];int visit[100],d[100],n;

class dijstra{

public: void read();int min(int a,int b);int getcur();void SSPT();

};

int dijstra::min(int a,int b){

if(a<=b)return a;

elsereturn b;

}

int dijstra::getcur(){

int i=1,curr;while(visit[i]==1)

i++;curr=i;for(i=curr+1;i<=n;i++)

if(d[i]<d[curr] && visit[i]==0)curr=i;

return curr;}

void dijstra::read(){

cout<<"\n Enter the number of nodes:";cin>>n;cout<<"\n Enter the cost matrix:\n";cout<<"\nEnter 0->diagonal elements and 99->No direct edge cost\n";for(i=1;i<=n;i++){

for(j=1;j<=n;j++){

cin>>cost[i][j];visit[i]=0;

}}cout<<"\n Enter the source vertex:\n";

Page 15: NIEIT ada lab manual (1)

cin>>source;visit[source]=1;

}

void dijstra::SSPT(){

for(i=1;i<=n;i++)d[i]=cost[source][i];

while(count<n){

curr=getcur();visit[curr]=1;

count++;for(i=1;i<=n;i++)if(visit[i]==0){

d[i]=min(d[i],d[curr]+cost[curr][i]);}

}cout<<"\n PATH DISTANCE\n";for(i=1;i<=n;i++)cout<<"\n("<<source<<","<<i<<")"<<"--->"<<d[i];

}

void main(){ dijstra d;

clrscr();d.read();d.SSPT();getch();

}

/*--------------------------------------------------------------------output:

Enter the number of nodes: 3Enter the cost matrix:Enter 0->diagonal elements and 99->No direct edge cost:0 10 3020 0 1520 5 0Enter the source vertex: 1PATH DISTANCE(1,1)---------> 0(1,2)---------> 10(1,3)---------> 25----------------------------------------------------------------------*/

Quick Sort

Quicksort is a well-known sorting algorithm developed by C. A. R. Hoare that, on

Page 16: NIEIT ada lab manual (1)

average, makes Θ(nlogn) (big O notation) comparisons to sort n items. However, in the worst

case, it makes Θ(n2) comparisons. Typically, quicksort is significantly faster in practice than

other Θ(nlogn) algorithms, because its inner loop can be efficiently implemented on most

architectures, and in most real-world data, it is possible to make design choices which minimize

the probability of requiring quadratic time.

Quicksort is a comparison sort and, in efficient implementations, is not a stable sort.

Quicksort sorts by employing a divide and conquer strategy to divide a list into two sub-lists.

Full example of quicksort on a random set of numbers. The boxed element is the pivot. It is

always chosen as the last element of the partition.

The steps are:

• Pick an element, called a pivot, from the list.

• Reorder the list so that all elements which are less than the pivot come before the pivot

and so that all elements greater than the pivot come after it (equal values can go either

way). After this partitioning, the pivot is in its final position. This is called the partition

operation.

• Recursively sort the sub-list of lesser elements and the sub-list of greater elements.

The base case of the recursion are lists of size zero or one, which are always sorted. In simple

pseudocode, the algorithm might be expressed as this:

function quicksort(array)

var list less, greater

if length(array) ≤ 1

return array

select and remove a pivot value pivot from array

for each x in array if x ≤ pivot then append x to less else append x to greater return concatenate(quicksort(less), pivot, quicksort(greater))

• Sort a given set of elements using Quick sort method and determine the time required sort the elements. Repeat the experiment for different values of n, the number of elements in the list to be sorted and plot a graph of the time taken versus n.

Page 17: NIEIT ada lab manual (1)

#include<iostream.h>#include<conio.h>#include<time.h>#include<stdlib.h>

class quicksort{ int n,a[1000]; int partition(int,int); void swap(int,int); public: void qsort(int,int); void getarray(); void putarray(); quicksort(int i) { n=i; }};int quicksort::partition(int low,int high){ int p,i,j; p=i=low; j=high+1; while(i<=j) { do

i++;while(a[i]<a[p]);

do j--;while(a[j]>a[p]);if(i<j) swap(i,j);

} swap(p,j); return j;}

void quicksort::qsort(int low,int high){ int mid; if(low<high) { mid=partition(low,high);

qsort(low,mid-1);qsort(mid+1,high);

}}

void quicksort::getarray(){ for(int i=0;i<n;i++) cin>>a[i];}

Page 18: NIEIT ada lab manual (1)

void quicksort::putarray(){ for(int i=0;i<n;i++) cout<<a[i]<<" ";}

void quicksort::swap(int i,int j){ int temp=a[i];

a[i]=a[j];a[j]=temp;

}

void main(){ int n; clock_t s,e; clrscr(); cout<<"\nEnter the no. of elements:\n "; cin>>n; s=clock(); quicksort a1(n); cout<<"\nEnter the elements of the array:\n"; a1.getarray(); cout<<"\nEntered elements of the array:\n"; a1.putarray(); cout<<"\nThe sorted array is:\n"; a1.qsort(0,n-1); e=clock(); a1.putarray(); cout<<"\nTime taken for sort\n"<<(e-s)/CLK_TCK; getch();}

Kruskal’s Algorithm

Kruskal's algorithm is an algorithm in graph theory that finds a minimum spanning tree for a

connected weighted graph. This means it finds a subset of the edges that forms a tree that

includes every vertex, where the total weight of all the edges in the tree is minimized. If the

graph is not connected, then it finds a minimum spanning forest (a minimum spanning tree for

each connected component). Kruskal's algorithm is an example of a greedy algorithm. This

algorithm first appeared in Proceedings of the American Mathematical Society, pp. 48–50 in

1956, and was written by Joseph Kruskal

It works as follows:

• create a forest F (a set of trees), where each vertex in the graph is a separate tree

Page 19: NIEIT ada lab manual (1)

• create a set S containing all the edges in the graph

• while S is nonempty

• remove an edge with minimum weight from S

• if that edge connects two different trees, then add it to the forest, combining two

trees into a single tree

• otherwise discard that edge.

At the termination of the algorithm, the forest has only one component and forms a minimum

spanning tree of the graph.

• Find Minimum Cost Spanning Tree of a given undirected graph using Kruskal’s algorithm.

#include<iostream.h>#include<conio.h>

int cost[10][10],root[10],min,edge=1,mincost=0;int i,j,a,b,u,v,n;

class MCST{

public: void kruskal();};

void MCST::kruskal(){

cout<<"Spanning Trees is:\n";while(edge<n){ for(i=1,min=999;i<=n;i++)

for(j=1;j<=n;j++)if(cost[i][j]<min){

min=cost[i][j];a=u=i;b=v=j;

}while(root[u])

u=root[u];while(root[v])

v=root[v];

if(u!=v){

Page 20: NIEIT ada lab manual (1)

edge++;cout<<"\n"<<"("<<a<<","<<b<<")"<<"="<<min;mincost+=min;root[v]=u;

}cost[a][b]=cost[b][a]=999;

}cout<<"\n Minimum cost = "<<mincost;

}

void main(){

MCST k;clrscr();cout<<"\n Enter the number of vertices:";

cin>>n;cout<<"\n Enter the cost matrix";for(i=1;i<=n;i++)

for(j=1;j<=n;j++){

cin>>cost[i][j];if(cost[i][j]==0)cost[i][j]=999;

} k.kruskal();

getch();}

Breadth-first search (BFS)

In graph theory, Breadth-First Search (BFS) is a graph search algorithm that begins at

the root node and explores all the neighboring nodes. Then for each of those nearest nodes, it

explores their unexplored neighbor nodes, and so on, until it finds the goal.BFS is an uninformed

search method that aims to expand and examine all nodes of a graph or combination of

sequences by systematically searching through every solution. In other words, it exhaustively

searches the entire graph or sequence without considering the goal until it finds it. It does not use

a heuristic algorithm.From the standpoint of the algorithm, all child nodes obtained by expanding

a node are added to a FIFO queue.

Algorithm (informal)

• Enqueue the root node.

• Dequeue a node and examine it.

• If the element sought is found in this node, quit the search and return a result.

Page 21: NIEIT ada lab manual (1)

• Otherwise enqueue any successors (the direct child nodes) that have not yet been

examined.

• If the queue is empty, every node on the graph has been examined – quit the search and

return "not found".

• Repeat from Step 2.

Note: Using a stack instead of a queue would turn this algorithm into a depth-first search. (DFS)

Applications

Breadth-first search can be used to solve many problems in graph theory, for example:

• Finding all connected components in a graph.

• Finding all nodes within one connected component

• Copying Collection, Cheney's algorithm

• Finding the shortest path between two nodes u and v (in an unweighted graph)

• Finding the shortest path between two nodes u and v (in a weighted graph: see talk page)

• Testing a graph for bipartiteness

• (Reverse) Cuthill–McKee mesh numbering

• a. Print all the nodes reachable from a given starting node in a digraph using BFS method.

#include<iostream.h>#include<conio.h>

int i,j,n,f=0,r=-1,source;int v,cost[10][10],q[10],q1[10];

class reach{

public: void bfs(int u); void read();

};

void reach::bfs(int u){

for(v=1;v<=n;v++){

Page 22: NIEIT ada lab manual (1)

if(cost[u][v]==1&&q1[v]==0)q[++r]=v;

}if(f<=r){

q1[q[f]]=1;bfs(q[f++]);

}}void reach::read(){ cout<<"Enter the number of vertices\n"; cin>>n; cout<<"Enter the cost adjacency matrix\n";

for(i=1;i<=n;i++)for(j=1;j<=n;j++)cin>>cost[i][j];

for(i=1;i<=n;i++) {

q[i]=0;q1[i]=0;

} cout<<"Enter the source vertex\n"; cin>>source; bfs(source); cout<<"The vertices from :"<<source<<"\n\n";

for(i=1;i<=n;i++){

if(q1[i]==1)cout<<i<<"\tis reachable\n";

}}void main(){ reach r; clrscr(); r.read(); getch();}

Depth-first search (DFS)

Depth First Search is an algorithm for traversing or searching a tree, tree structure, or

graph. One starts at the root (selecting some node as the root in the graph case) and explores as

far as possible along each branch before backtracking.

Applications

Algorithms where DFS is used:

• Finding connected components.

Page 23: NIEIT ada lab manual (1)

• Topological sorting.

• Finding 2-(edge or vertex)-connected components.

• Finding strongly connected components.

• Solving puzzles with only one solution, such as mazes.

b. Check whether a given graph is connected or not using DFS method. #include<iostream.h>#include<conio.h>

int n,j,source,cost[10][10],s[10],i,connected,flag;class graph{

public: void dfs(int n,int u,int cost[10][10],int s[10]); void read();

};

void graph::dfs(int n,int u,int cost[10][10],int s[10]){ int v; s[u]=1; for(v=1;v<=n;v++) if(cost[u][v]==1&&!s[v]) dfs(n,v,cost,s);}

void graph::read(){ cout<<"Enter the number of vertices\n"; cin>>n; cout<<"Enter the cost matrix\n";

for(i=1;i<=n;i++)for(j=1;j<=n;j++)

cin>>cost[i][j]; connected=0; for(j=1;j<=n;j++) {

for(i=1;i<=n;i++)s[i]=0;

dfs(n,j,cost,s);flag=0;for(i=1;i<=n;i++)

if(s[i]==0) flag=1;

if(flag==0)connected=1;

} if(connected==1)

cout<<"The graph is connected\n"; else

cout<<"the graph is not connected\n";

Page 24: NIEIT ada lab manual (1)

}

void main(){ graph g; clrscr(); g.read(); getch();}

Subset construction

Backtracking is a refinement of the brute force approach, which systematically searches

for a solution to a problem among all available options. It does so by assuming that the solutions

are represented by vectors (v1, ..., vm) of values and by traversing, in a depth first manner, the

domains of the vectors until the solutions are found.

The objective of this problem is to find as many subsets as possible whose individual sum

equals some constant value.

• Find a subset of a given set S = {sl,s2,.....,sn} of n positive integers whose sum is equal to a given positive integer d. For example, if S= {1, 2, 5, 6, 8} and d = 9 there are two solutions{1,2,6}and{1,8}.A suitable message is to be displayed if the given problem instance doesn't have a solution.

#include<iostream.h>#include<conio.h>#include<stdlib.h>

int s[10],d,n,visit[10],i,k,r=0, flag=0;class set{

public: void subset(int sum,int i,int r); void read();

};

void set::subset(int sum,int i,int r){

int j;visit[i]=1;if(sum+s[i]==d){

flag=1;cout<<"\n Subset "<<++k<<": ";for(j=0;j<=i;j++)if(visit[j])cout<<s[j]<<"\t";

}else if(sum+s[i]+s[i+1]<=d)subset(sum+s[i],i+1,r-s[i]);

Page 25: NIEIT ada lab manual (1)

if((sum+r-s[i]>=d) && (sum+s[i+1]<=d)){

visit[i]=0;subset(sum,i+1,r-s[i]);

}}

void set::read(){

cout<<"\n Enter the number of elements:\n";cin>>n;cout<<"\n Enter the elements in ascending order:";for(i=0;i<n;i++){

cout<<"\n\t:";cin>>s[i];

}cout<<"\n Enter the sum:";cin>>d;for(i=0;i<n;i++)r+=s[i];subset(0,0,r);if(!flag)cout<<"Solution doesnot exist:\n";

}

void main(){

set s;clrscr();s.read();getch();

}

******************************************************************************* /* OUTPUT Enter the number of elements:4

Enter the elements: :3

:5

:6

:7

Enter the sum:15

Subset 1: 3 5 7

*/

Page 26: NIEIT ada lab manual (1)

*******************************************************************************

The Boyer–Moore–Horspool algorithm or Horspool's algorithm

Is an algorithm for finding substrings in strings. It is a simplification of the Boyer-Moore

algorithm which is related to the Knuth-Morris-Pratt algorithm. The algorithm trades space for

time in order to obtain an average-case complexity of O(N) on random text, although it has

O(MN) in the worst case. The length of the pattern is M and the length of the search string is N.

• a. Implement Horspool algorithm for String Matching. #include<iostream.h>#include<conio.h>#include<string.h>#include<stdio.h>

int table[256],flag;char t[100],p[100];

class horse{

public: void shift_table(char p[],int m); int horspool(char t[],char p[]); void read();

};

void horse::shift_table(char p[],int m){

int i,j;for(i=0;i<127;i++)

table[i]=m;for(j=0;j<m-1;j++)

table[p[j]]=m-1-j;}

int horse::horspool(char t[],char p[]){

int i,k,m,n;m=strlen(p);n=strlen(t);shift_table(p,m);i=m-1;while(i<=n-1){

k=0;while(k<=m-1 && p[m-1-k]==t[i-k])k++;if(k==m)

Page 27: NIEIT ada lab manual (1)

return i-m+1;elsei+=table[t[i]];

}return -1;

}

void horse::read(){

cout<<"\n Enter the text:\n\t";gets(t);cout<<"\n Enter the pattern:\n\t";gets(p);

flag=horspool(t,p);

if(flag==-1)cout<<"\n Pattern string not found";elsecout<<"\n Pattern string found at position= "<<flag+1<<"\n";getch();

}

void main(){

clrscr();horse h;h.read();

}****************************************************************************** /* OUTPUT Run 1: Enter the text:

ferrari rules

Enter the pattern: fiat

No match

Run 2: Enter the text:

jim_saw_me_in_the_barber_shop

Enter the pattern: barber

Match found at position 19 */*******************************************************************************

Binomial coefficient

Page 28: NIEIT ada lab manual (1)

The Binomial coefficients C(n, k) is the number of ways of choosing a subset of k

elements from a set of n elements. It arises in probability and statistics, e.g., the

probability of flipping a biased coin (with probability p of heads) n times and getting

exactly k heads is C(n, k) pk (1-p)k. One formula for computing binomial coefficients is

C(n, k) = n! / (k! (n-k)!). This formula is not so amenable to direct computation because

the intermediate results may overflow, even if the final answer does not. For example

C(100, 15) = 253338471349988640 fits in a 64-bit long, but the binary representation of

100! is 525 bits long. Pascal's identity expresses C(n, k) in terms of smaller binomial

coefficients:

To understand why Pascal's identity is valid, consider some arbitrary element x. To choose k of n elements, we either select element x (in which case we still need to choose k-1 of the remaining n-1 elements), or we don't select element x (in which case we still need to choose k of the remaining n-1 elements).

The code for calculating binomial coefficients is shown below

long binomial(int n, int k)

{

if (k == 0) return 1;

if (n == 0) return 0;

return binomial(n-1, k) + binomial(n-1, k-1);

b. Find the Binomial Co-efficient using Dynamic Programming.

#include<iostream.h>#include<conio.h>

int c[20][20],n,k;

class bino{ public: int min(int a,int b);

void binomial(int n,int k); void bino::read();

};

int bino::min(int a,int b){

if(a<b)return a;

elsereturn b;

}

Page 29: NIEIT ada lab manual (1)

void bino::binomial(int n,int k){

int i,j;cout<<"\n The table of co-efficients are...\n";for(i=0;i<=n;i++){

for(j=0;j<=min(i,k);j++){

if(j==0 || j==i)c[i][j]=1;

elsec[i][j]=c[i-1][j]+c[i-1][j-1];

// cout<<"\t"<<c[i][j];}cout<<"\n";

}cout<<"\n The binomial co-efficient = "<<c[n][k];

}

void bino::read(){

cout<<"\n Enter n:";cin>>n;cout<<"\n Enter k:";cin>>k;if(k<0 || n<0 || n<k)

cout<<"\n Invalid entry";else

binomial(n,k);getch();

}

void main(){

clrscr();bino b;b.read();

}******************************************************************************* /* OUTPUT RUN 1: Enter n:5

Enter k:3

The table of co-efficients are... 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 5 10 10

Page 30: NIEIT ada lab manual (1)

The binomial co-efficient = 10

RUN 2: Enter n:3

Enter k:7

Invalid entry */

*******************************************************************************

Prim’s Algorithm

Prim's algorithm is an algorithm in graph theory that finds a minimum spanning tree for

a connected weighted graph. This means it finds a subset of the edges that forms a tree that

includes every vertex, where the total weight of all the edges in the tree is minimized. The

algorithm was developed in 1930 by Czech mathematician Vojtěch Jarník and later

independently by computer scientist Robert C. Prim in 1957 and rediscovered by Edsger Dijkstra

in 1959. Therefore it is sometimes called the DJP algorithm, the Jarník algorithm, or the

Prim-Jarník algorithm.

The algorithm continuously increases the size of a tree starting with a single vertex until it spans

all the vertices.

• Input: A connected weighted graph with vertices V and edges E.

• Initialize: Vnew = {x}, where x is an arbitrary node (starting point) from V, Enew = {}

• Repeat until Vnew = V:

• Choose edge (u,v) with minimal weight such that u is in Vnew and v is not (if there

are multiple edges with the same weight, choose arbitrarily but consistently)

• Add v to Vnew, add (u, v) to Enew

• Output: Vnew and Enew describe a minimal spanning tree

Page 31: NIEIT ada lab manual (1)

• Find Minimum Cost Spanning Tree of a given undirected graph using Prim’s algorithm.

#include<iostream.h>#include<conio.h>

int i,j,count=1,source,curr,cost[10][10],r[10],s[10],sum=0;int visit[100],d[100],n;

class prims{

public: void read(); int min(int a,int b); int getcur(); void MCST();

};int prims::min(int a,int b){

if(a<=b)return a;

elsereturn b;

}

int prims::getcur(){

int i=1,curr;while(visit[i]==1)

i++;curr=i;for(i=curr+1;i<=n;i++)

if(d[i]<d[curr] && visit[i]==0)curr=i;

return curr;}

void prims::read(){

cout<<"\n Enter the number of nodes:";cin>>n;cout<<"\n Enter the cost matrix:\n";cout<<"\nEnter 0->diagonal elements and 99->No direct edge cost\n";for(i=1;i<=n;i++){

for(j=1;j<=n;j++){

cin>>cost[i][j];visit[i]=0;

}}

}

void prims::MCST()

Page 32: NIEIT ada lab manual (1)

{for(i=1;i<=n;i++){

d[i]=cost[1][i];r[i]=1;

}

visit[1]=1;while(count<n){

curr=getcur();visit[curr]=1;

count++;for(i=1;i<=n;i++)if(visit[i]==0){

s[i]=d[i];d[i]=min(d[i],cost[curr][i]);if(d[i]!=s[i])r[i]=curr;

}}cout<<"\n EDGES WEIGHTS\n";for(i=1;i<=n;i++)

cout<<"\n("<<r[i]<<","<<i<<")"<<"--->"<<d[i]; cout<<"\nThe minimum cost spanning tree is\t";

for(i=1;i<=n;i++)sum=sum+d[i];

cout<<sum;}

void main(){ prims p;

clrscr();p.read();p.MCST();getch();

}

/*--------------------------------------------------------------------output:

Enter the number of nodes: 5Enter the cost matrix:Enter 0->diagonal elements and 99->No direct edge cost0 1 3 99 51 0 4 6 993 4 0 2 699 6 2 0 995 99 6 99 0

EDGES WEIGHTS(1,1)---------> 0

Page 33: NIEIT ada lab manual (1)

(1,2)---------> 1(1,3)---------> 3(3,4)---------> 2(1,5)---------> 5

The minimum cost spanning tree is 11----------------------------------------------------------------------*/

Warshall’s Algorithm

Warshall's algorithm enables to compute the transitive closure of the adjacency matrix

of any digraph. The transitive closure of a digraph G=(V,E) with set of vertices and

edges is defined as Boolean matrix (only 0’s and 1’s ) of size n X n. Such that

a[i,,j]= 1 if there is a non trival directed path

else a[i,j]=0

Here input is an digraph it should be supplied as an adjucancy matrix.

• a. Compute the transitive closure of a given directed graph using Warshall's algorithm.

#include<iostream.h>#include<conio.h>

int i,j,k,n,a[10][10],p[10][10],flag=1;

class tclose{

public: void warshall(int n, int a[10][10], int p[10][10]); void read(int n, int a[10][10]); void write(int n, int a[10][10]);

};

void tclose::warshall(int n, int a[10][10], int p[10][10]){ for(i=0;i<n;i++)

for(j=0;j<n;j++) p[i][j]=a[i][j];

for(k=0;k<n;k++)for(i=0;i<n;i++)

for(j=0;j<n;j++)if((p[i][k]==1 && p[k][j]==1))

p[i][j]=1;}

void tclose::read(int n, int a[10][10]){

for(i=0;i<n;i++)

Page 34: NIEIT ada lab manual (1)

for(j=0;j<n;j++) cin>>a[i][j];

}

void tclose::write(int n, int a[10][10]){

for(i=0;i<n;i++){ for(j=0;j<n;j++) { cout<<a[i][j]<<"\t"; if(a[i][j]!=1) flag=0; }cout<<"\n";}/*if(flag)

cout<<"\n Graph is connected";else

cout<<"\n Graph is disconnected";*/}

void main(){

tclose t;clrscr();cout<<"\n enter the no. of nodes:";cin>>n;cout<<"enter the adjacent matrix:";t.read(n,a);t.warshall(n,a,p);cout<<"The Transitive closure(path matrix)\n";t.write(n,p);getch();

}

*******************************************************************************/* -----OUTPUT-----

Enter the no of nodes : 4

Enter the Adjucency Matrix0 1 0 00 0 0 10 0 0 01 0 1 0

The closute matrix is :

1 1 1 11 1 1 10 0 0 0

Page 35: NIEIT ada lab manual (1)

1 1 1 1*/

*******************************************************************************

13 b. Implement Floyds algorithm for the all pairs Shortest path problem.

#include<iostream.h>#include<conio.h>int i,j,k,n;int cost[10][10],d[10][10];

class floy{

public: int min(int a , int b); void floyd(int n, int cost[10][10], int d[10][10]); void read(int n, int a[10][10]); void write(int n, int a[10][10]);

};

int floy::min(int a , int b){

return a<b?a:b;}

void floy::floyd(int n, int cost[10][10], int d[10][10]){

for(i=0;i<n;i++)for(j=0;j<n;j++)

d[i][j]=cost[i][j];

for(k=0;k<n;k++){

for(i=0;i<n;i++){

for(j=0;j<n;j++){

d[i][j]=min(d[i][j],d[i][k]+d[k][j]);}

}}

}

void floy::read(int n, int a[10][10]){

for(i=0;i<n;i++) for(j=0;j<n;j++)

cin>>a[i][j];}

void floy::write(int n, int a[10][10]){ for(i=0;i<n;i++)

Page 36: NIEIT ada lab manual (1)

{ for(j=0;j<n;j++) {

cout<<"\t"<<a[i][j]; } cout<<"\n";

}}

void main(){

clrscr();floy f;cout<<"Enter the number of nodes:\n";cin>>n;cout<<"\nEnter the cost adjacency matrix:\n";cout<<"Enter0->Self loop 99->No direct Edge cost:\n\n";f.read(n,cost);f.floyd(n,cost,d);cout<<"\nSolution to all pairs shortest path problem is:\n";f.write(n,d);getch();

}

*******************************************************************************/* -----OUTPUT-----

Enter the no of nodes : 4

Enter the Cost Adjucency Matrix Enter0->Self loop 99->No direct Edge cost:

0 99 3 992 0 99 9999 7 0 16 99 99 0

nSolution to all pairs shortest path problem is

0 10 3 42 0 5 67 7 0 16 16 9 0

*/*******************************************************************************

N Queen Problem

Page 37: NIEIT ada lab manual (1)

The n-queens problem consists in placing n non-attacking queens on an n-by-n chess

board. A queen can attack another queen vertically, horizontally, or diagonally. E.g.

placing a queen on a central square of the board blocks the row and column where it is

placed, as well as the two diagonals (rising and falling) at whose intersection the queen

was placed. The algorithm to solve this problem uses backtracking, but we will unroll

the recursion. The basic idea is to place queens column by column, starting at the left.

New queens must not be attacked by the ones to the left that have already been placed

on the board. We place another queen in the next column if a consistent position is

found. All rows in the current column are checked. We have found a solution if we

placed a queen in the rightmost column.

• Implement N Queen's problem using Back Tracking.

#include<iostream.h>#include<conio.h>#include<stdlib.h>

int a[100],count=0, i,n;class queen{

public: int place(int pos);void printsol(int n);void nqueens(int n);void read();

};int queen::place(int pos){

int i;for(i=1;i<pos;i++){

if((a[i]==a[pos])||((abs(a[i]-a[pos])==abs(i-pos))))return 0;

}return 1;

}void queen::printsol(int n){

int i,j;count++;cout<<"\n\nSolution: "<<count;for(i=1;i<=n;i++){

cout<<"\n\n ";for(j=1;j<=n;j++){

if(a[j]==i)cout<<"Q ";

else

Page 38: NIEIT ada lab manual (1)

cout<<"* ";}getch();

}}void queen::nqueens(int n){

int k=1;a[k]=0;while(k!=0){

a[k]=a[k]+1;while(a[k]<=n && !place(k))

a[k]++;if(a[k]<= n)

if(k==n)printsol(n);

else{

k++;a[k]=0;

}else

k--;}

}void queen::read(){ cout<<"\nEnter the no of queens : "; cin>>n; if(n==2||n==3) {

cout<<"No solution:\n";getch();exit(0);

} nqueens(n); cout<<"\nTotal no of solutions =" <<count; getch();}void main(){

queen q;clrscr();q.read();

}/* -----OUTPUT-----

Enter the no of queens : 4

Solution: 1* * Q *Q * * ** * * Q* Q * *

Page 39: NIEIT ada lab manual (1)

Solution: 2* Q * ** * * QQ * * ** * Q *

Total no of solutions = 2*/

Algorithms Lab VIVA Questions

• Difference between recursive and non-recursive Algorithm

• Define Algorithm and Mention various methods of Specifying an algorithm

• What is analysis and Design of algorithm• Difference between Binary search and linear

search.• Define heap and Explain construction of Heap

with one numeric example 5,35,25,45,20,55,25,45,50,10,30 and 15

• Difference between Merge sort and Bubble sort

• Define dynamic programming with example

• Explain the Concept of greedy method by considering change making problem

• Difference between DFS and BFS

• Define backtracking

• Explain Horspool algorithm with text string

• Difference between Kruskal’s and Prim’s algorithm

• For the given graph implement floyd’s Alogrithm

• Explain the concept of Dijksthra’s algorithm with example

• Difference between Floyd’s and Warshall’s algorithm

• Explain concept of knapsack Problem using dynamic programming