DAA Record
DAA Record
Laboratory Manual
Submitted By:
<Name>
<USN>
ISE (B-2 batch)
I, <Name>, like to express my sincere appreciation to Neetha ma’am who contributed to the
development of this lab manual. The dedication and support were invaluable in creating a resource
that enhances the learning experience.
Thank you Neetha ma’am, for the expertise and guidance in merge sort,quick sort, binary search
tree, BFS, topological order and so on in the DAA lab.
The insights and feedback greatly enriched the content of this manual. Thank you ma’am for the
assistance in designing the experiments and providing valuable input during the manual's
development. I would like to acknowledge for providing valuable insights that contributed to its
refinement.
BANGALORE UNIVERSITY
CERTIFICATE
This is to certify that, <Name> (<USN>), has satisfactorily completed the course of Experiments in
Practical Design And Analysis Of Algorithm , prescribed by Department of CSE, Bangalore
University, during the academic year 2022- 23.
_______________________ _______________________
Date: _______________
Introduction
1 Sort a given set of elements using Merge sort 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 graph of the
time taken versus number of elements. The elements can be read from
file or generated using random number generator
2 Sort a given set of elements using Quick sort 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 graph of the
time taken versus number of elements. The elements can be read from a
file or generated using random number generator.
4 Print all the nodes reachable from a given starting node in a digraph using
the BFS method.
7 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 number of elements.
8 Search for a pattern string in a given text using Horspool String Matching
algorithm.
Algorithm Design
The important aspects of algorithm design include creating an efficient algorithm to solve a problem
in an efficient way using minimum time and space. To solve a problem, different approaches can
be followed. Some of them can be efficient with respect to time consumption, whereas other
approaches may be memory efficient. However, one has to keep in mind that both time
consumption and memory usage cannot be optimised simultaneously. If we require an algorithm to
run in less time, we have to invest in more memory and if we require an algorithm to run with lesser
memory, we need to have more time.
Characteristics of Algorithms
By considering an algorithm for a specific problem, we can begin to develop pattern recognition so
that similar types of problems can be solved by the help of this algorithm. Algorithms are often
quite different from one another, though the objective of these algorithms are the same. For
example, we know that a set of numbers can be sorted using different algorithms. Number of
comparisons performed by one algorithm may vary with others for the same input. Hence, time
complexity of those algorithms may differ. At the same time, we need to calculate the memory
space required by each algorithm. Analysis of an algorithm is the process of analysing the problem
solving capability of the algorithm in terms of the time and size required (the size of memory for
storage while implementation). However, the main concern of analysis of algorithms is the required
time or performance. Generally, we perform the following types of analysis
The elements can be read from file or generated using random number generator.Merge sort is
the sorting technique that follows the divide and conquer approach.
The important part of the merge sort is the MERGE function. This function performs the merging of
two sorted subarrays that are
So, the inputs of the MERGE function are A [], beg, mid, and end.
Algorithm
Merge_Sort(arr,beg,end)
If beg<end
Merge_Sort(arr,beg,mid)
Merge_Sort(arr, mid+1,end)
End if
END Merge_Sort
Program
import java.util.Scanner;
import java.util.Random;
Merge Sort
Enter the Number of times the algorithm should Run: 5
Random Number Generated are at POS 0 as follows :
534 861 7 563 12 937 70 454 834 551
Elements after Sorting are
7 12 70 454 534 551 563 834 861 937
Random Number Generated are at POS 1 as follows :
904 585 782 420 450 292 889 886 716 157
Elements after Sorting are
157 292 420 450 585 716 782 886 889 904
Random Number Generated are at POS 2 as follows :
695 163 390 543 668 317 962 852 290 316
Elements after Sorting are
163 290 316 317 390 543 668 695 852 962
Random Number Generated are at POS 3 as follows :
999 612 96 616 350 914 308 954 309 15
Elements after Sorting are
15 96 308 309 350 612 616 914 954 999
Random Number Generated are at POS 4 as follows :
624 510 232 742 946 824 624 459 590 495
Elements after Sorting are
232 459 495 510 590 624 624 742 824 946
Graph
2. Sort a given set of elements using Quick sort 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 graph of the time taken versus number of
elements.
The elements can be read from a file or generated using a random number
generator. Quicksort is the other important sorting algorithm that is based on the
divide-and-conquer approach.
Unlike mergesort, which divides its input elements according to their position in the array, quicksort
divides them according to their value.
Algorithm:
Partition Algorithm:
then i ? i + 1
}
Program
import java.util.Random;
import java.util.Scanner;
scan.close();
}
}
Output:
Graph:
3. Perform insert and delete operations in Binary Search Tree
A Binary Search Tree (BST) is a hierarchical data structure where each node has at most two
children: a left child with a value less than the node and a right child with a value greater than the
node. This ordering property is maintained throughout the tree, making search, insert, and delete
operations efficient with an average time complexity of O(log n), where n is the number of nodes. The
left and right subtrees of every node are also BSTs, ensuring sorted access to the elements. These
properties facilitate fast searching and manipulation of data in a self-balancing binary tree structure.
class BinarySearchTree {
static class Node {
int data;
Node left, right;
Node root;
BinarySearchTree() {
root = null;
}
void inorder() {
inorderRec(root);
}
void inorderRec(Node root) {
if (root != null) {
inorderRec(root.left);
System.out.print(root.data + " ");
inorderRec(root.right);
}
}
Output
Inorder traversal:
20 30 40 50 60 70 80
Delete 20:
30 40 50 60 70 80
Delete 30:
40 50 60 70 80
4. Print all the nodes reachable from a given starting node in a digraph using the BFS
method.
Breadth-First Search (BFS) is a graph traversal algorithm that explores vertices level by level, visiting
all neighbours of a node before moving on to the next level. Starting from the initial node, BFS
systematically explores all reachable nodes, employing a queue to maintain the order of exploration.
It ensures the shortest path is discovered first, making it ideal for finding the shortest path in
unweighted graphs. BFS is complete and guarantees optimality when searching for a solution in a
graph with uniform edge costs. Its time complexity is O(V + E), where V is the number of vertices and
E is the number of edges in the graph.
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
Output:
Topological Sorting is an algorithm used for directed acyclic graphs (DAGs) to linearly order the
vertices such that for every directed edge (u, v), vertex u comes before v in the ordering. The
algorithm utilises depth-first search (DFS) to traverse the graph and assigns a topological order to
each vertex. Topological sorting is applicable only to DAGs, as cyclic dependencies are not allowed.
The time complexity of the algorithm is O(V + E), where V is the number of vertices, and E is the
number of edges. It finds applications in task scheduling, dependency resolution, and compiler
optimization.
import java.util.*;
public TopologicalSort(int v) {
V = v;
adjList = new LinkedList[v];
for (int i = 0; i < v; ++i)
adjList[i] = new LinkedList<>();
}
Output:
Warshall's Algorithm, also known as the Floyd-Warshall Algorithm, is used for finding the transitive
closure of a directed graph. It computes the shortest paths between all pairs of vertices in a graph,
taking into account both direct and indirect paths. The algorithm utilises dynamic programming and
iteratively updates the shortest path matrix. It works for both positive and negative edge weights but
does not handle negative cycles. The time complexity of Warshall's Algorithm is O(V^3), where V is
the number of vertices. It is particularly useful for scenarios like network routing and determining
reachability in a directed graph.
import java.util.Scanner;
Heap Sort is a comparison-based sorting algorithm that builds a max-heap from the given array, then
repeatedly extracts the maximum element (root of the heap) and swaps it with the last element. The heap
size is reduced, and the heap property is maintained through the heapify operation. This process
continues until the entire array is sorted. The algorithm has a time complexity of O(n log n), making it
efficient for large datasets.
import java.util.*;
Output:
Horspool String Matching algorithm is a technique used to efficiently search for a pattern string within a
given text . It operates by pre-computing a shift table based on characters in the pattern to determine the
maximum possible shift when a mismatch occurs during the search process. This shift table helps in
shifting unnecessary comparisons , optimising the search
import java.util.Scanner;
public class HorspoolStringMatching {
public static int[] shiftTable(String pattern) {
Output:
The 0/1 Knapsack Problem is a fundamental optimization challenge addressed through dynamic
programming. In this problem, a set of items, each with a specific weight and value, must be selectively
included in a knapsack with a given capacity to maximise the total value. The "0/1" aspect denotes the
binary decision for each item—either it is entirely included or excluded. Dynamic programming offers an
efficient solution strategy, involving the creation of a table to store optimal solutions for subproblems. By
systematically filling this table, the algorithm builds up to the optimal solution, avoiding redundant
computations and showcasing the versatility of dynamic programming in solving real-world resource
allocation and optimization dilemmas.
import java.util.Scanner;
public class KnapsackDP {
Prim's algorithm is a fundamental algorithm in graph theory used for finding the minimum spanning tree of
a connected, undirected graph with weighted edges. The algorithm begins by selecting an arbitrary node
as the starting point and then iteratively grows the spanning tree by adding the shortest edge that
connects a vertex in the tree to a vertex outside the tree. This process continues until all vertices are
included in the spanning tree. The resulting tree has the minimum possible total edge weight among all
spanning trees of the graph. Implementing Prim's algorithm in Java involves maintaining data structures
like priority queues or min-heaps to efficiently select the minimum-weight edges at each step. The Java
implementation should effectively represent the graph, manage the edges, and provide a clear and
concise solution for computing the minimum spanning tree. Efficiently handling data structures and
ensuring proper edge selection are crucial aspects of a successful implementation.
import java.util.Scanner;
public class prims {
public static void main(String[] args) {
int w[][]=new int[10][10];
int n,i,j,s,k=0;
int min;
int sum=0;
int u=0,v=0;
int flag=0;
int sol[]=new int[10];
System.out.println("Enter the number of vertices");
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
for(i=1;i<=n;i++)
sol[i]=0;
System.out.println("Enter the weighted graph");
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
w[i][j]=sc.nextInt();
System.out.println("Enter the source vertex");
s=sc.nextInt();
sol[s]=1;
k=1;
while (k<=n-1)
{
min=99;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(sol[i]==1&&sol[j]==0)
if(i!=j && min>w[i][j])
{
min=w[i][j];
u=i;
v=j;
}
sol[v]=1;
sum=sum+min;
k++;
System.out.println(u+"->"+v+"="+min);
}
for(i=1;i<=n;i++)
if(sol[i]==0)
flag=1;
if(flag==1)
System.out.println("No spanning tree");
else
System.out.println("The cost of minimum spanning tree is"+sum);
sc.close();
}
}
Output:
Enter the number of vertices
6
Enter the weighted graph
0 3 99 99 6 5
3 0 1 99 99 4
99 1 0 6 99 4
99 99 6 0 8 5
6 99 99 8 0 2
5 4 4 5 2 0
Enter the source vertex
1
1->2=3
2->3=1
2->6=4
6->5=2
6->4=5
The cost of minimum spanning tree is15
11. Find Minimum Cost Spanning Tree of a given undirected graph using Kruskal's
algorithm
Kruskal's algorithm is a widely used method for finding the Minimum Cost Spanning Tree (MCST) of an
undirected graph. The primary objective of this algorithm is to connect all vertices of the given graph with
the minimum possible total edge weight, ensuring that a tree is formed without any cycles. The algorithm
starts by sorting all the edges of the graph in ascending order based on their weights. It then iteratively
selects the smallest edge that does not form a cycle when added to the growing spanning tree. This
process continues until all vertices are included in the tree, resulting in an optimal solution that minimizes
the overall edge weights. Kruskal's algorithm is efficient, particularly for sparse graphs, and its simplicity
makes it a popular choice for solving minimum spanning tree problems in various applications, such as
network design and optimization.
import java.util.Scanner;
public class kruskal {
int parent[]=new int[10];
int find(int m){
int p=m;
while(parent[p]!=0)
p=parent[p];
return p;
}
void union(int i,int j)
{
if(i<j)
parent[i]=j;
else
parent[j]=i;
}
void krkl(int[][]a, int n)
{
int u=0,v=0,min,k=0,i,j,sum=0;
while(k<n-1)
{
min=99;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(a[i][j]<min&&i!=j)
{
min=a[i][j];
u=i;
v=j;
}
i=find(u);
j=find(v);
if(i!=j)
{
union(i,j);
System.out.println("("+u+","+v+")"+"="+a[u][v]);
sum=sum+a[u][v];
k++;
}
a[u][v]=a[v][u]=99;
}
System.out.println("The cost of minimum spanning tree = "+sum);
}
public static void main(String[] args) {
int a[][]=new int[10][10];
int i,j;
System.out.println("Enter the number of vertices of the graph");
Scanner sc=new Scanner(System.in);
int n;
n=sc.nextInt();
System.out.println("Enter the wieghted matrix");
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
a[i][j]=sc.nextInt();
kruskal k=new kruskal();
k.krkl(a,n);
sc.close();
}
}
Output:
Enter the number of vertices of the graph
6
Enter the wieghted matrix
0 3 99 99 6 5
3 0 1 99 99 4
99 1 0 6 99 4
99 99 6 0 8 5
6 99 99 8 0 2
5 4 4 5 2 0
(2,3)=1
(5,6)=2
(1,2)=3
(2,6)=4
(4,6)=5
The cost of minimum spanning tree = 15
12. From a given vertex in a weighted connected graph, find shortest paths to other
vertices using Dijkstra's algorithm.
In the context of graph theory, the problem statement revolves around employing Dijkstra's algorithm to
determine the shortest paths from a specified starting vertex to all other vertices in a connected graph with
weighted edges. Dijkstra's algorithm, a fundamental and widely used algorithm in the realm of computer
science and network routing, efficiently calculates the minimum distance from the source vertex to every
other vertex by iteratively exploring the neighbouring nodes and updating the distance values. The
weighted connected graph signifies that each edge connecting the vertices possesses a numerical weight,
representing the cost or distance between the linked vertices. The objective is to unveil the most optimal
paths, considering the cumulative weights, from the given origin to all other vertices, thereby facilitating a
comprehensive understanding of the shortest routes within the network.
import java.util.Scanner;
public class Dijkstra {
OUTPUT :
enter the number of vertices
5
enter the weighted matrix
0 3 99 7 99
3 0 4 2 99
99 4 0 5 6
5 2 5 0 4
99 99 6 4 0
enter the source vertex
0
the shortest path between source 0 remaining vertices are
0 ->1 =3
0 ->1 ->2 =7
0 ->1 ->3 =5
0 ->1 ->3 ->4 =9
13. Solve Travelling Sale Person Problem Using Dynamic Programming approach.
The Traveling Salesman Problem (TSP) is a classic optimization challenge where the goal is to find the
most efficient route that visits a set of cities exactly once and returns to the starting city. The objective is to
minimize the total distance or cost of the journey. This problem is NP-hard, meaning there's no known
polynomial-time solution for all cases. It has applications in logistics, transportation, and network
optimization. Various algorithms, such as genetic algorithms and dynamic programming, are employed to
find near-optimal solutions. TSP's computational complexity increases exponentially with the number of
cities, making it a fundamental problem in combinatorial optimization. .
import java.util.Scanner;
class TSPExp {
int weight[][], n, tour[], finalCost;
final int INF = 1000;
TSPExp() {
Scanner s = new Scanner(System.in);
System.out.println("Enter no. of nodes:=>");
n = s.nextInt();
weight = new int[n][n];
tour = new int[n - 1];
class TSP {
public static void main(String args[]) {
TSPExp obj = new TSPExp();
}
}
Output:
import java.util.Scanner;
private static boolean isSafe(int[][] board, int row, int col, int N) {
for (int i = 0; i < col; i++) {
if (board[row][i] == 1) {
return false;
}
}
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if (board[i][j] == 1) {
return false;
}
}
for (int i = row, j = col; i < N && j >= 0; i++, j--) {
if (board[i][j] == 1) {
return false;
}
}
return true;
}
Dynamic programming is used to solve the Subset Sum Problem efficiently. The approach involves
creating a two-dimensional array where each cell represents whether a specific sum can be achieved with
a subset of the given numbers. The base case initialises the array with True for the target sum and False
for others. Iterating through the array, each cell is filled based on the inclusion or exclusion of the current
number. The final cell contains the solution, indicating if the target sum is reachable. This dynamic
programming technique optimally avoids redundant calculations, providing a polynomial-time solution to
the Subset Sum Problem.
import java.util.ArrayList;
import java.util.Scanner;
if (!dp[n][sum]) {
return false;
}
int i = n, j = sum;
return true;
}
if (hasSubsetSum) {
System.out.println("Subset contributing to the sum: " + subset);
}