You are on page 1of 43

DEPARTMENT OF COMPUTER ENGINEERING

Design and Analysis of Algorithm using C Lab


Course Code: -21CEL47A
Laboratory Manual

Academic Year: 2022 – 2023


Batch :2021-2025
Year -II
Semester: IV

Prepared by Approved by
Mrs.Anjali Vyas Dr.S.P.Manikandan
HOD-CE
INSTITUTION
Vision

To emerge as an institute of eminence in the fields of engineering, technology and management in serving the
industry and the nation by empowering students with a high degree of technical, managerial and practical
competence.

Mission

To strengthen the theoretical, practical and ethical dimensions of the learning process by fostering a culture of
research and innovation among faculty members and students.

To encourage long-term interaction between the academia and industry through their involvement in the design of
curriculum and its hands-on implementation.

To strengthen and mould students in professional, ethical, social and environmental dimensions by
encouraging participation in co-curricular and extracurricular activities.
To develop value based socially responsible professionals for the betterment of the society

Quality Policy

To emerge as an institute of eminence in the fields of engineering, technology and management in serving the
industry and the nation by empowering students with a high degree of technical, managerial and practical
competence.

Values
Academic Freedom Professionalism
Innovation Inclusiveness
Integrity Social Responsibility
DEPARTMENT OF COMPUTER ENGINEERING
Vision

To produce engineers, researchers and technologists with managerial skills of highest competence who would
be able to solve the challenges of society.

Mission

To impart high quality professional training, practical experience and value education in the Computer
Engineering.

To pursue creative research in Computer Engineering in order to serve the engineering community and
society.

To prepare and encourage a student for Lifelong learning to meet career and ethical challenges through active
participation in co-curricular and extracurricular activities.
Program Educational Objectives (PEOs)
To prepare globally competent graduates having strong fundamentals of Computer
PEO1: Engineering domain knowledge, updated with modern technology to provide effective
solutions for engineering problems.

PEO2: To acuminate graduates with ability to adapt and develop projects towards the latest
technological era of the Computing and IT sector with a high degree of innovative ideas.

PEO3: To produce committed and motivated graduates with research attitude, investigative
approach, and multidisciplinary thinking for implementation of strategic tasks.

PEO 4: To shape the graduates with strong managerial and communication skills to work and
learn continuously and effectively as individuals as well as in teams.
PEO to Mission Statement Mapping

Mission Statements PEO1 PEO2 PEO3 PEO4

To impart high quality professional training, practical


experience and value education in the Computer Engineering. 3 2 2 2

To pursue creative research in Computer Engineering in


order toserve the engineering community and society. 3 2 2 2

To prepare and encourage a student for Lifelong learning to


2 2 3 3
meet career and ethical challenges through active
participation in co- curricular and extracurricular activities.

Program Specific Outcomes (PSOs)


A graduate of the Computer Engineering Program will demonstrate

PSO1: The ability to apply the knowledge of core science, engineering mathematics and engineering
fundamentals to design and develop the computing systems.

PSO2: The ability to provide effective and efficient real time solutions to problems in computer engineering
using acquired knowledge in various domains
Program Outcomes (POs) with Graduate Attributes
Engineering knowledge: Apply the knowledge of mathematics, science, Engineering
PO1 fundamentals, and an Engineering specialization to the solution of complex
Engineering problems in Computer Engineering.
Problem analysis: Identify, formulate, review research literature, and analyze
PO2 complex Engineering problems in Computer Engineering reaching substantiated
conclusions using first principles of mathematics, natural sciences, and Engineering
sciences.
Design / Development of Solutions: Design solutions for complex Engineering
PO3 problems and design system components or processes of Computer Engineering that
meet the specified needs with appropriate consideration for the public health and
safety, and the cultural, societal, and Environmental considerations.
Conduct Investigations of Complex Problems: Use research-based knowledge and
PO4 research methods including design of experiments in Computer Engineering, analysis
and interpretation of data, and synthesis of the information to provide valid conclusions.
Modern Tool Usage: Create, select, and apply appropriate techniques, resources, and
PO5 modern Engineering and IT tools including prediction and modeling to complex
Engineering activities in Computer Engineering with an understanding of the
limitations.
The Engineer and Society: Apply reasoning informed by the contextual knowledge
PO6 to assess societal, health, safety, legal and cultural issues and the consequent
responsibilities relevant to the professional engineering practice in Computer
Engineering.
Environment and Sustainability: Understand the impact of the professional
PO7 Engineering solutions of Computer Engineering in societal and Environmental
contexts, and demonstrate the knowledge of, and need for sustainable development.
Ethics: Apply ethical principles and commit to professional ethics and responsibilities
PO8
and norms of the Engineering practice.
Individual and Team Work: Function effectively as an individual, and as a member
PO9
or leader in diverse teams, and in multidisciplinary settings.
Communication Skills: Communicate effectively on complex Engineering activities
PO10 with the Engineering community and with society at large, such as, being able to
comprehend and write effective reports and design documentation, make effective
presentations, and give and receive clear instructions.
Project Management and Finance: Demonstrate knowledge and understanding of the
PO11 Engineering and management principles and apply these to one’s own work, as a
member and leader in a team, to manage projects and in multidisciplinary Environments.
Life-long Learning: Recognize the need for, and have the preparation and ability to
PO12 engage in independent and life-long learning in the broadest context of technological
change.
LAB RUBRICS

Course- Design and Analysis of Algorithm Laboratory


Course code-21CEL47A
Semester-4th
Internal Assessment Marks: 50
Divided into two components:
1. Continuous Assessment: 10 marks
2. Internal Test: 40 marks

1. Continuous Assessment:
i) Will be carried out in every lab (for labs -12 programs)
ii) Each program will be evaluated for 10 marks
iii) Totally for 12 lab programs it will be 120 marks. This will be scaled down to 10.
iv) During the semester, 2 internal tests will be conducted for 50 marks each. The total 50 marks for
the internal tests, will be scaled down to 40.

Break up of 10 marks (in every lab):


Will be carried out in every lab (for 12 lab programs)
Attributes Descriptors Scores
Complete program with proper variable naming, proper
3
commenting
Complete program with not so proper variable naming,
3
Program Write- poor commenting
up(3)
Incomplete code 2

Not written 1

Passes all specified test cases efficiently 5


Execution &
Fails in some test cases 3
Results (3)
Incomplete execution 1

Answers correctly 2
Viva Voce (2)
Answers satisfactorily 1
Do not answer any question 0

Record Submits in time and completed (during subsequent lab) 2


completion and
submission (2) Fails to submit the record in time / incomplete submission 0

2. Internal Test:
Break up of 50 marks (for each of the 2 internal tests) which is scaled down to 40 marks after the
conduction of 2 internal tests:
The 1st lab internal will comprise of the first 8 lab programs and the 2nd lab internal will comprise of
the next 7 lab programs.
Attributes Descriptors Scores
Complete program with proper variable naming, proper
5
commenting
Complete program with not so proper variable naming,
3-4
Program poor commenting
Write-up (5)
Incomplete code 1-2

Not written 0

Passes all specified test cases efficiently 15


Execution &
Fails in some test cases 10-14
Results (15)
Incomplete execution 1-9

Answers 100% questions correctly 5

Answers 75% questions correctly 3-4


Viva Voce (5)
Answers satisfactorily 1-2

Does not answer any question 0


SEE

Assessment Marks: 25

Session End Examination is conducted for 50 marks.

Attributes Descriptors Scores


Complete program with proper variable naming, proper
10
commenting
Complete program with not so proper variable naming,
6-7
Program Write- poor commenting
up (10)
Incomplete code 4-5

Not written 0

Passes all specified test cases efficiently 30


Execution &
Fails in some test cases 18-22
Results (30)
Incomplete execution 10-12

Answers 100% questions correctly 10

Answers 75% questions correctly 6-7


Viva Voce (10)
Answers satisfactorily 4-5

Does not answer any question 0


DESIGN AND ANALYSIS OF ALGORITHM using C LAB

Course Code : 21CEL47A Credits: 01


L: T: P: S : 0: 0: 1: 0 CIE Marks: 50
Exam Hours: : 03 SEE Marks: 50

Course Outcomes: At the end of the Course, the Student will be able to
CO# COURSE OUTCOME
21CEL47A.1 Write the complexities of various applications in different domains
21CEL47A.2 Apply efficient algorithms to solve problems in various domains
21CEL47A.3 Analyze suitable design technique to develop efficient algorithms
21CEL47A.4 Compare, implement and understand when to apply various design techniques

Mapping of Course Outcomes to Program Outcomes


PO1 PO2 PO3 PO4 PO5 PO6 PO7 PO8 PO9 PO10 PO11 PO12 PSO1 PSO2
21CEL47A.1 3 3 3 3 3 - - 3 3 - - 3 3 3
21CEL47A.2 3 3 3 3 3 - - 3 3 - - 3 3 3
21CEL47A.3 3 3 3 3 3 - - 3 3 - - 3 3 3
21CEL47A.4 3 3 3 3 3 - - 3 3 - - 3 3 3
Correlation levels: 1-Slight (Low) 2-Moderate (Medium) 3-Substantial (High)

Sl. LIST OF HOURS COs


No. EXPERIMENTS
Write a program to find GCD of two numbers using
1 differential algorithms 2 CO1
Write a program to Implement Sieve of Eratosthenes to
2 CO1
2 generate Prime Numbers Between Given Range
Write a program to implement string matching using Brute
2 CO1
3 Force
Write a program to implement Merge Sort CO2,
4 3
CO3
Write a program to implement Quick Sort CO2,
5 3
CO3
Write a program to obtain minimum cost spanning tree CO2,
3
6 using Prim’s Algorithm CO3
Write a program to obtain minimum cost spanning CO2,
3
7 tree using Kruskal’s Algorithm CO3
Write a program to obtain shortest path using Djikstra’s CO2,
3
8 algorithm CO3
Write a program to compute Binomial Coefficient CO2,
9 3
CO3
Write a program to compute Transitive closure using CO2,
3
10 Warshall’s algorithm CO3
Write a program to implement Breadth First search CO2,
11 3
CO3
Write a program to implement Depth First search CO2,
12 3
CO3
Write a program to implement Topological sorting CO2,
13 3
CO3
Write a program to implement Subset Sum problem
3 CO4
14 using Backtracking
Write a program to implement N Queens problem
3 CO4
15 using Backtracking

Assessment Pattern
CIE- Continuous Internal Evaluation (50 Marks)

Blooms Taxonomy Tests


Marks (Out of 25) 50
L1: Remember -
L2: Understand -
L3: Apply 50
L4: Analyze -
L5: Evaluate -
L6: Create -

SEE- Semester End Examination (50 Marks)

Blooms Taxonomy Marks (Out of 50)


L1: Remember -
L2: Understand -
L3: Apply 50
L4: Analyze -
L5: Evaluate -
L6: Create -
1. Write a program to find GCD of two numbers using differential algorithms

Algorithm:

1. First, we ask the user to input two positive integers.


2. Then, we swap the values of a and b if a is less than b. This is necessary for the
differential algorithm to work properly.
3. Next, we apply the differential algorithm using a while loop. In each iteration of the loop,
we calculate the difference between a and b, and update the values of a and b accordingly.
4. Finally, we print the value of a, which is the GCD of the two numbers

Program:

#include <stdio.h>
int main() {
int a, b;
printf("Enter two positive integers: ");
scanf("%d %d", &a, &b);

// Swap a and b if necessary


if (a < b) {
int temp = a;
a = b;
b = temp;
}

// Apply the differential algorithm


while (b != 0) {
int diff = a - b;
if (diff >= b) {
a = diff;
} else {
a = b;
b = diff;
}
}

printf("GCD = %d\n", a);

return 0;
}

Output:
Enter two positive integers: 5 10
GCD = 5
2. Write a program to Implement Sieve of Eratosthenes to generate Prime Numbers
Between Given Range

Algorithm:

1. First, we ask the user to input the upper limit of the range.
2. We create a boolean array called "prime" of size n+1, and initialize all entries to true.
The array will store whether each number in the range is prime or composite.
3. We iterate over the array from 2 to the square root of n (inclusive). For each prime
number p, we mark all of its multiples as composite by setting their corresponding
entries in the "prime" array to false.
4. After the loop is finished, all entries in the "prime" array that are still true correspond
to prime numbers between 2 and n. We print them out using a loop.
5. The program ends by returning 0.

Program:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

void SieveOfEratosthenes(int n){


// Create a boolean array "prime[0..n]" and initialize all entries it as true.
// A value in prime[i] will finally be false if i is Not a prime, else true.
bool prime[n + 1];
memset(prime, true, sizeof(prime));

for (int p = 2; p * p <= n; p++) {


if (prime[p] == true) { // If prime[p] is not changed, then it is a prime
// Update all multiples of p greater than or equal to the square of it numbers which are
// multiple of p and are less than p^2 are already been marked.
for (int i = p * p; i <= n; i += p)
prime[i] = false; }
}
// Print all prime numbers
for (int p = 2; p <= n; p++)
if (prime[p])
printf("%d ",p);}

int main()
{ int n = 30;
printf("Following are the prime numbers smaller than or equal to %d \n", n);
SieveOfEratosthenes(n);
return 0;}

Output:
Following are the prime numbers smaller than or equal to 30
2 3 5 7 11 13 17 19 23 29
3. Write a program to implement string matching using Brute Force

Algorithm:

1. First, we ask the user to input the text string and the pattern string.
2. We create a function called "stringMatch" that takes two arguments: the text string
and the pattern string.
3. Inside the stringMatch function, we initialize two variables "i" and "j" to 0. We also
get the lengths of the text and pattern strings and store them in variables "n" and "m".
4. We iterate over the text string using a for loop that starts at index 0 and ends at index
n - m. This is because we don't need to check the last m characters of the text string,
since the pattern can't match there.
5. Inside the first for loop, we iterate over the pattern string using a nested for loop. We
compare each character of the pattern string with the corresponding character of the
text string starting at index i.
6. If any characters don't match, we break out of the loop and move on to the next
iteration of the outer loop.
7. If all characters in the pattern string match the corresponding characters in the text
string, we print out the index where the pattern was found.
8. In the main function, we call the stringMatch function with the text and pattern strings
as arguments.
9. The program ends by returning 0.

Program:

#include <stdio.h>
#include <string.h>
void stringMatch(char* text, char* pattern) {
int i, j;
int n = strlen(text);
int m = strlen(pattern);
// Iterate over the text string, checking for matches with the pattern
for (i = 0; i <= n - m; i++) {
// Iterate over the pattern, comparing each character with the corresponding character in the
text
for (j = 0; j < m; j++) {
if (text[i+j] != pattern[j])
break;
}
// If all characters in the pattern match the corresponding characters in the text,
// then we have found a match
if (j == m)
printf("Pattern found at index %d\n", i);
}
}
int main() {
char text[1000], pattern[1000];

printf("Enter the text string: ");


fgets(text, sizeof(text), stdin);
printf("Enter the pattern string: ");
fgets(pattern, sizeof(pattern), stdin);
// Remove the newline character from the end of the input strings
text[strcspn(text, "\n")] = 0;
pattern[strcspn(pattern, "\n")] = 0;

// Call the stringMatch function to perform the string matching


stringMatch(text, pattern);
return 0;
}

Output:

Enter the text string: lolipop


Enter the pattern string: pop
Pattern found at index 4
4. Write a program to implement Merge Sort

Algorithm:

1. We define a function called "merge" that takes four arguments: the array to be
sorted, the left index of the subarray, the middle index of the subarray, and the
right index of the subarray.
2. Inside the "merge" function, we first calculate the sizes of the left and right
subarrays. We then create temporary arrays to store the left and right subarrays.
3. We copy the data from the main array into the temporary arrays.
4. We then merge the temporary arrays back into the main array by comparing the
first elements of each subarray and copying the smaller element into the main
array.
5. Finally, we copy any remaining elements of the left or right subarray into the main
array.
6. We define a function called "mergeSort" that takes three arguments: the array to
be sorted, the left index of the subarray, and the right index of the subarray.
7. Inside the "mergeSort" function, we first check if the left index is less than the
right index. If not, then the subarray is already sorted and we can exit the function.

Program:

#include <stdio.h>
void merge(int arr[], int l, int m, int r) {
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;

// Create temporary arrays to store the left and right subarrays


int L[n1], R[n2];
// Copy data to the temporary arrays
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
for (j = 0; j < n2; j++)
R[j] = arr[m + 1 + j];

// Merge the temporary arrays back into the main array


i = 0;
j = 0;
k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++; }
else {
arr[k] = R[j];
j++;}
k++; }
// Copy any remaining elements of the left subarray into the main array
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}

// Copy any remaining elements of the right subarray into the main array
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;
// Sort the left and right subarrays recursively
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r); // Merge the sorted subarrays
}
}

int main() {
int arr[] = {38, 27, 43, 3, 9, 82, 10};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Original array: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
mergeSort(arr, 0, n - 1);
printf("\nSorted array: ");
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}

Output:

Original array: 38 27 43 3 9 82 10
Sorted array: 3 9 10 27 38 43 82
5. Write a program to implement Quick Sort

Algorithm:

1. We define a function called "swap" that takes two integer pointers as arguments and
swaps the values at those pointers.
2. We define a function called "partition" that takes three arguments: the array to be
sorted, the left index of the subarray, and the right index of the subarray.
3. Inside the "partition" function, we choose the last element of the subarray as the pivot.
We then loop through the subarray, moving elements smaller than the pivot to the left
of the pivot.
4. After the loop, we swap the pivot with the element immediately to its right, which
puts the pivot in its final sorted position. We then return the index of the pivot.
5. We define a function called "quickSort" that takes three arguments: the array to be
sorted, the left index of the subarray, and the right index of the subarray.
6. Inside the "quickSort" function, we first check if the left index is less than the right
index. If not, then the subarray is already sorted and we can exit the function.
7. We partition the subarray using the "partition" function, which gives us the index of
the pivot.
8. We then recursively call "quickSort" on the left subarray and the right subarray, using
the pivot index as the dividing point.
9. We define the main function, which creates an array, prints the original array, sorts the
array using quickSort, and then prints the sorted array.

Program:

#include <stdio.h>
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}

int partition(int arr[], int low, int high) {


int pivot = arr[high]; // choose the last element as the pivot
int i = (low - 1);

for (int j = low; j <= high - 1; j++) {


if (arr[j] < pivot) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[high]);
return (i + 1);
}

void quickSort(int arr[], int low, int high) {


if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}

int main() {
int arr[] = {38, 27, 43, 3, 9, 82, 10};
int n = sizeof(arr) / sizeof(arr[0]);

printf("Original array: ");


for (int i = 0; i < n; i++)
printf("%d ", arr[i]);

quickSort(arr, 0, n - 1);

printf("\nSorted array: ");


for (int i = 0; i < n; i++)
printf("%d ", arr[i]);

return 0;
}

Output:

Original array: 38 27 43 3 9 82 10
Sorted array: 3 9 10 27 38 43 82
6. Write a program to obtain minimum cost spanning tree using Prim’s Algorithm

Algorithm:

1. We define a function called "minKey" that takes two arrays as arguments: an array of
key values for each vertex, and an array indicating whether each vertex is in the
minimum spanning tree set.
2. Inside the "minKey" function, we loop through all the vertices and find the vertex
with the minimum key value that is not yet in the minimum spanning tree set.
3. We define a function called "printMST" that takes two arrays as arguments: an array
of parent vertices and the adjacency matrix representing the graph.
4. Inside the "printMST" function, we loop through all the vertices except the root (0),
and print the edge connecting each vertex to its parent, along with its weight.
5. We define a function called "primMST" that takes the adjacency matrix representing
the graph as an argument.
6. Inside the "primMST" function, we initialize three arrays: an array of parent vertices,
an array of key values for each vertex, and an array indicating whether each vertex is
in the minimum spanning tree set.
7. We set the key value of the root vertex (0) to 0, and its parent to -1, and set the key
value of all other vertices to INT_MAX.
8. We loop through all the vertices except the root (0), and find the vertex with the
minimum key value that is not yet in the minimum spanning tree set using the
"minKey" function

Program:

#include <stdio.h>
#include <limits.h>

#define V 5 // number of vertices in the graph

int minKey(int key[], int mstSet[]) {


int min = INT_MAX, min_index;

for (int v = 0; v < V; v++) {


if (mstSet[v] == 0 && key[v] < min) {
min = key[v];
min_index = v;
}
}

return min_index;
}

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


printf("Edge Weight\n");
for (int i = 1; i < V; i++) {
printf("%d - %d %d \n", parent[i], i, graph[i][parent[i]]);
}
}

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


int parent[V]; // array to store the parent of each vertex
int key[V]; // array to store the key (minimum weight edge) of each vertex
int mstSet[V]; // array to keep track of vertices included in MST

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


key[i] = INT_MAX;
mstSet[i] = 0;
}

key[0] = 0; // start with vertex 0


parent[0] = -1; // first node is always the root of MST

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


int u = minKey(key, mstSet);
mstSet[u] = 1;

for (int v = 0; v < V; v++) {


if (graph[u][v] && mstSet[v] == 0 && 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;
}

Output:

Edge Weight
0-1 2
1-2 3
0-3 6
1-4 5
7. Write a program to obtain minimum cost spanning tree using Kruskal’s Algorithm

In Kruskal’s algorithm, sort all edges of the given graph in increasing order. Then it keeps on
adding new edges and nodes in the MST if the newly added edge does not form a cycle. It
picks the minimum weighted edge at first at the maximum weighted edge at last. Thus we can
say that it makes a locally optimal choice in each step in order to find the optimal solution.
Hence this is a Greedy Algorithm.

Steps to find MST


1. Sort all the edges in non-decreasing order of their weight.
2. Pick the smallest edge. Check if it forms a cycle with the spanning tree formed so far.
If the cycle is not formed, include this edge. Else, discard it.
3. Repeat step#2 until there are (V-1) edges in the spanning tree.
4. Step 2 uses the Union-Find algorithm to detect cycles.

Program:

#include <stdio.h>
#include <stdlib.h>

// Comparator function to use in sorting


int comparator(const void* p1, const void* p2)
{
const int(*x)[3] = p1;
const int(*y)[3] = p2;

return (*x)[2] - (*y)[2];


}

// Initialization of parent[] and rank[] arrays


void makeSet(int parent[], int rank[], int n)
{
for (int i = 0; i < n; i++) {
parent[i] = i;
rank[i] = 0;
}
}

// Function to find the parent of a node


int findParent(int parent[], int component)
{
if (parent[component] == component)
return component;

return parent[component]
= findParent(parent, parent[component]);
}

// Function to unite two sets


void unionSet(int u, int v, int parent[], int rank[], int n)
{
// Finding the parents
u = findParent(parent, u);
v = findParent(parent, v);

if (rank[u] < rank[v]) {


parent[u] = v;
}
else if (rank[u] > rank[v]) {
parent[v] = u;
}
else {
parent[v] = u;

// Since the rank increases if


// the ranks of two sets are same
rank[u]++;
}
}

// Function to find the MST


void kruskalAlgo(int n, int edge[n][3])
{
// First we sort the edge array in ascending order
// so that we can access minimum distances/cost
qsort(edge, n, sizeof(edge[0]), comparator);

int parent[n];
int rank[n];

// Function to initialize parent[] and rank[]


makeSet(parent, rank, n);

// To store the minimun cost


int minCost = 0;

printf(
"Following are the edges in the constructed MST\n");
for (int i = 0; i < n; i++) {
int v1 = findParent(parent, edge[i][0]);
int v2 = findParent(parent, edge[i][1]);
int wt = edge[i][2];

// If the parents are different that


// means they are in different sets so
// union them
if (v1 != v2) {
unionSet(v1, v2, parent, rank, n);
minCost += wt;
printf("%d -- %d == %d\n", edge[i][0],
edge[i][1], wt);
}
}

printf("Minimum Cost Spanning Tree: %d\n", minCost);


}

// Driver code
int main()
{
int edge[5][3] = { { 0, 1, 10 },
{ 0, 2, 6 },
{ 0, 3, 5 },
{ 1, 3, 15 },
{ 2, 3, 4 } };

kruskalAlgo(5, edge);

return 0;
}

Output:

Following are the edges in the constructed MST


2 -- 3 == 4
0 -- 3 == 5
0 -- 1 == 10
Minimum Cost Spanning Tree:
8. Write a program to obtain shortest path using Djikstra’s algorithm

Output: 0 4 12 19 21 11 9 8 14
Explanation: The distance from 0 to 1 = 4.
The minimum distance from 0 to 2 = 12. 0->1->2
The minimum distance from 0 to 3 = 19. 0->1->2->3
The minimum distance from 0 to 4 = 21. 0->7->6->5->4
The minimum distance from 0 to 5 = 11. 0->7->6->5
The minimum distance from 0 to 6 = 9. 0->7->6
The minimum distance from 0 to 7 = 8. 0->7
The minimum distance from 0 to 8 = 14. 0->1->2->8

Like Prim’s MST, generate a SPT (shortest path tree) with a given source as a root. Maintain
two sets, one set contains vertices included in the shortest-path tree, other set includes
vertices not yet included in the shortest-path tree. At every step of the algorithm, find a vertex
that is in the other set (set not yet included) and has a minimum distance from the source.

Follow the steps below to solve the problem:

1. Create a set sptSet (shortest path tree set) that keeps track of vertices included in the
shortest path tree, i.e., whose minimum distance from the source is calculated and
finalized. Initially, this set is empty.
2. Assign a distance value to all vertices in the input graph. Initialize all distance values
as INFINITE. Assign the distance value as 0 for the source vertex so that it is picked
first.
3. While sptSet doesn’t include all vertices
4. Pick a vertex u that is not there in sptSet and has a minimum distance value.
5. Include u to sptSet.
6. Then update the distance value of all adjacent vertices of u.
7. To update the distance values, iterate through all adjacent vertices.
8. For every adjacent vertex v, if the sum of the distance value of u (from source) and
weight of edge u-v, is less than the distance value of v, then update the distance value
of v.
Note: We use a boolean array sptSet[] to represent the set of vertices included in SPT. If a
value sptSet[v] is true, then vertex v is included in SPT, otherwise not. Array dist[] is used to
store the shortest distance values of all vertices.

Program:
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>

// Number of vertices in the graph


#define V 9

// A utility function to find the vertex with minimum


// distance value, from the set of vertices not yet included
// in shortest path tree
int minDistance(int dist[], bool sptSet[])
{
// Initialize min value
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;
}

// A utility function to print the constructed distance


// array
void printSolution(int dist[])
{
printf("Vertex \t\t Distance from Source\n");
for (int i = 0; i < V; i++)
printf("%d \t\t\t\t %d\n", i, dist[i]);
}

// Function that implements Dijkstra's single source


// shortest path algorithm for a graph represented using
// adjacency matrix representation
void dijkstra(int graph[V][V], int src)
{
int dist[V]; // The output array. dist[i] will hold the shortest distance from src to i
bool sptSet[V]; // sptSet[i] will be true if vertex i is included in shortest
// path tree or shortest distance from src to i is finalized
// Initialize all distances as INFINITE and stpSet[] as false
for (int i = 0; i < V; i++)
dist[i] = INT_MAX, sptSet[i] = false;
// Distance of source vertex from itself is always 0
dist[src] = 0;
// Find shortest path for all vertices
for (int count = 0; count < V - 1; count++) {
// Pick the minimum distance vertex from the set of vertices not yet processed. u is
always equal to src in the first iteration.
int u = minDistance(dist, sptSet);
// Mark the picked vertex as processed
sptSet[u] = true;
// Update dist value of the adjacent vertices of the picked vertex.
for (int v = 0; v < V; v++)
// Update dist[v] only if is not in sptSet, there is an edge from u to v, and total
// weight of path from src to v through u is smaller than current value of dist[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); // print the constructed distance array
}

// driver's code
int main()
{
/* Let us create the example graph discussed above */
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;
}

Output:
Vertex Distance from Source
0 0
1 4
2 12
3 19
4 21
5 11
6 9
7 8
8 14
9. Write a program to compute Binomial Coefficient

Algorithm:

1. ‘binomialCoeff’ function takes two arguments n and k which represent the


values of nCk to be computed.
2. It uses a recursive approach to compute the binomial coefficient by breaking
the problem into two subproblems and summing up their values.
3. The base case of the recursion is when k is equal to 0 or n, in which case the
binomial coefficient is 1.
4. The main function initializes the values of n and k and calls the binomialCoeff
function to compute the binomial coefficient of (n,k). It then prints the result
to the console.

Program:

#include <stdio.h>
int binomialCoeff(int n, int k) {
if (k == 0 || k == n)
return 1;
else
return binomialCoeff(n - 1, k - 1) + binomialCoeff(n - 1, k);
}

int main() {
int n = 5, k = 2;
printf("Binomial Coefficient of (%d,%d) is %d", n, k, binomialCoeff(n, k));
return 0;
}

Output:

Binomial Coefficient of (5,2) is 10


10. Write a program to compute Transitive closure using Warshall’s algorithm

Algorithm:

1. The printMatrix function takes a matrix as input and prints it to the console.
2. The transitiveClosure function takes the adjacency matrix of a directed graph as
input and computes its transitive closure using Warshall's algorithm.
3. It initializes the transitive closure matrix with the adjacency matrix and updates it
using the algorithm.
4. The main function initializes the adjacency matrix of a directed graph, calls the
transitiveClosure function to compute its transitive closure, and prints the
resulting matrix to the console.

Program:

#include <stdio.h>
#define V 4 // Number of vertices in the graph
void printMatrix(int matrix[][V]) {
printf("Transitive Closure Matrix:\n");
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++)
printf("%d ", matrix[i][j]);
printf("\n"); }}
void transitiveClosure(int graph[][V]) {
int tc[V][V]; // Initialize transitive closure matrix with the adjacency matrix
for (int i = 0; i < V; i++)
for (int j = 0; j < V; j++)
tc[i][j] = graph[i][j];

for (int k = 0; k < V; k++) // Update transitive closure matrix


for (int i = 0; i < V; i++)
for (int j = 0; j < V; j++)
tc[i][j] = tc[i][j] || (tc[i][k] && tc[k][j]);
printMatrix(tc); // Print transitive closure matrix }

int main() {
int graph[V][V] = {{1, 1, 0, 1},
{0, 1, 1, 0},
{0, 0, 1, 1},
{0, 0, 0, 1}}; // Adjacency matrix of the directed graph
transitiveClosure(graph); // Compute transitive closure
return 0;}

Output:
Transitive Closure Matrix:
1111
0110
0011
0001
11. Write a program to implement Breadth First search

Algorithm:

1. The enqueue function takes a vertex as input and adds it to the rear of the queue.
2. The dequeue function removes and returns the front element of the queue.
3. The bfs function takes the starting vertex and the number of vertices in the graph
as input and performs BFS on the graph starting from the given vertex.
4. It uses the enqueue and dequeue functions to add and remove vertices from the
queue.
5. The visited array keeps track of the visited vertices, and the adj array is the
adjacency matrix of the graph.
6. The main function takes the adjacency matrix and the starting vertex as input and
calls the bfs function to perform BFS on the graph starting from the given vertex.

Program:

#include <stdio.h>
#include <stdlib.h>
#define SIZE 40

struct queue {
int items[SIZE];
int front;
int rear;
};

struct queue* createQueue();


void enqueue(struct queue* q, int);
int dequeue(struct queue* q);
void display(struct queue* q);
int isEmpty(struct queue* q);
void printQueue(struct queue* q);

struct node {
int vertex;
struct node* next;
};

struct node* createNode(int);

struct Graph {
int numVertices;
struct node** adjLists;
int* visited;
};
// BFS algorithm
void bfs(struct Graph* graph, int startVertex) {
struct queue* q = createQueue();

graph->visited[startVertex] = 1;
enqueue(q, startVertex);

while (!isEmpty(q)) {
printQueue(q);
int currentVertex = dequeue(q);
printf("Visited %d\n", currentVertex);

struct node* temp = graph->adjLists[currentVertex];

while (temp) {
int adjVertex = temp->vertex;

if (graph->visited[adjVertex] == 0) {
graph->visited[adjVertex] = 1;
enqueue(q, adjVertex);
}
temp = temp->next;
}
}
}

// Creating a node
struct node* createNode(int v) {
struct node* newNode = malloc(sizeof(struct node));
newNode->vertex = v;
newNode->next = NULL;
return newNode;
}

// Creating a graph
struct Graph* createGraph(int vertices) {
struct Graph* graph = malloc(sizeof(struct Graph));
graph->numVertices = vertices;

graph->adjLists = malloc(vertices * sizeof(struct node*));


graph->visited = malloc(vertices * sizeof(int));

int i;
for (i = 0; i < vertices; i++) {
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}

return graph;
}
// Add edge
void addEdge(struct Graph* graph, int src, int dest) {
// Add edge from src to dest
struct node* newNode = createNode(dest);
newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;

// Add edge from dest to src


newNode = createNode(src);
newNode->next = graph->adjLists[dest];
graph->adjLists[dest] = newNode;
}

// Create a queue
struct queue* createQueue() {
struct queue* q = malloc(sizeof(struct queue));
q->front = -1;
q->rear = -1;
return q;
}

// Check if the queue is empty


int isEmpty(struct queue* q) {
if (q->rear == -1)
return 1;
else
return 0;
}

// Adding elements into queue


void enqueue(struct queue* q, int value) {
if (q->rear == SIZE - 1)
printf("\nQueue is Full!!");
else {
if (q->front == -1)
q->front = 0;
q->rear++;
q->items[q->rear] = value;
}
}

// Removing elements from queue


int dequeue(struct queue* q) {
int item;
if (isEmpty(q)) {
printf("Queue is empty");
item = -1;
} else {
item = q->items[q->front];
q->front++;
if (q->front > q->rear) {
printf("Resetting queue ");
q->front = q->rear = -1;
}
}
return item;
}

// Print the queue


void printQueue(struct queue* q) {
int i = q->front;

if (isEmpty(q)) {
printf("Queue is empty");
} else {
printf("\nQueue contains \n");
for (i = q->front; i < q->rear + 1; i++) {
printf("%d ", q->items[i]);
}
}
}

int main() {
struct Graph* graph = createGraph(6);
addEdge(graph, 0, 1);
addEdge(graph, 0, 2);
addEdge(graph, 1, 2);
addEdge(graph, 1, 4);
addEdge(graph, 1, 3);
addEdge(graph, 2, 4);
addEdge(graph, 3, 4);

bfs(graph, 0);
return 0;
}

Output:
Queue contains
0 Resetting queue Visited 0
Queue contains
2 1 Visited 2
Queue contains
1 4 Visited 1
Queue contains
4 3 Visited 4
Queue contains
3 Resetting queue Visited 3
12. Write a program to implement Depth First search

Algorithm:

1. Start by putting any one of the graph's vertices on top of a stack.


2. Take the top item of the stack and add it to the visited list.
3. Create a list of that vertex's adjacent nodes. Add the ones which aren't in the visited
list to the top of the stack.
4. Keep repeating steps 2 and 3 until the stack is empty.

Program:

#include <stdio.h>
#include <stdlib.h>

struct node {
int vertex;
struct node* next;
};

struct node* createNode(int v);

struct Graph {
int numVertices;
int* visited;

// We need int** to store a two dimensional array.


// Similary, we need struct node** to store an array of Linked lists
struct node** adjLists;
};

// DFS algo
void DFS(struct Graph* graph, int vertex) {
struct node* adjList = graph->adjLists[vertex];
struct node* temp = adjList;

graph->visited[vertex] = 1;
printf("Visited %d \n", vertex);

while (temp != NULL) {


int connectedVertex = temp->vertex;

if (graph->visited[connectedVertex] == 0) {
DFS(graph, connectedVertex);
}
temp = temp->next;
}}
// Create a node
struct node* createNode(int v) {
struct node* newNode = malloc(sizeof(struct node));
newNode->vertex = v;
newNode->next = NULL;
return newNode;
}

// Create graph
struct Graph* createGraph(int vertices) {
struct Graph* graph = malloc(sizeof(struct Graph));
graph->numVertices = vertices;

graph->adjLists = malloc(vertices * sizeof(struct node*));

graph->visited = malloc(vertices * sizeof(int));

int i;
for (i = 0; i < vertices; i++) {
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}
return graph;
}

// Add edge
void addEdge(struct Graph* graph, int src, int dest) {
// Add edge from src to dest
struct node* newNode = createNode(dest);
newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;

// Add edge from dest to src


newNode = createNode(src);
newNode->next = graph->adjLists[dest];
graph->adjLists[dest] = newNode;
}

// Print the graph


void printGraph(struct Graph* graph) {
int v;
for (v = 0; v < graph->numVertices; v++) {
struct node* temp = graph->adjLists[v];
printf("\n Adjacency list of vertex %d\n ", v);
while (temp) {
printf("%d -> ", temp->vertex);
temp = temp->next;
}
printf("\n");
}}

int main() {
struct Graph* graph = createGraph(4);
addEdge(graph, 0, 1);
addEdge(graph, 0, 2);
addEdge(graph, 1, 2);
addEdge(graph, 2, 3);

printGraph(graph);

DFS(graph, 2);

return 0;
}

Output:
Adjacency list of vertex 0
2 -> 1 ->

Adjacency list of vertex 1


2 -> 0 ->

Adjacency list of vertex 2


3 -> 1 -> 0 ->

Adjacency list of vertex 3


2 ->
Visited 2
Visited 3
Visited 1
Visited 0
13. Write a program to implement Topological sorting

Algorithm:

1. Store each vertex’s In-Degree in an array D


2. Initialize queue with all “in-degree=0” vertices
3. While there are vertices remaining in the queue:
(a) Dequeue and output a vertex
(b) Reduce In-Degree of all vertices adjacent to it by 1
(c) Enqueue any of these vertices whose In-Degree became zero
4. If all vertices are output then success, otherwise there is a cycle.

Program:

#include<stdio.h>
#include<conio.h>

int main(){
int i,j,k,n,a[10][10],indeg[10],flag[10],count=0;

printf("Enter the no of vertices:\n");


scanf("%d",&n);
printf("Enter the adjacency matrix:\n");

for(i=0;i<n;i++){
printf("Enter row %d\n",i+1);
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);}

for(i=0;i<n;i++){
indeg[i]=0;
flag[i]=0; }
for(i=0;i<n;i++)
for(j=0;j<n;j++)
indeg[i]=indeg[i]+a[j][i];

printf("\nThe topological order is:");


while(count<n){
for(k=0;k<n;k++){
if((indeg[k]==0) && (flag[k]==0)){
printf("%d ",(k+1));
flag [k]=1;
}

for(i=0;i<n;i++){
if(a[i][k]==1)
indeg[k]--;
} }
count++;
} return 0;}
Output:

Enter the no of vertices:


4
Enter the adjacency matrix:
Enter row 1
0110
Enter row 2
0001
Enter row 3
0001
Enter row 4
0000

The topological order is:1 2 3 4


14. Write a program to implement Subset Sum problem using Backtracking

Algorithm:
1. i: Item index
2. sum: Sum of integers selected so far
3. remSum: Size of remaining problem i.e. (W - sum)
// Output: Solution tuple X

4. if FEASIBLE SUB_SET() == 1 then


5. if (sum == W) then
print X [1...i]
end
6. else
X [i + 1] <- 1
7. SUB SET PROBLEM(i +1. sum + w[i] + 1 ,W, remSum - w * [i] + 1 )
8. X[i+1] <- 0 //Exclude the " item
9. SUB_SET_PROBLEM( i + 1, sum, W, remSum- w[i] + 1 )
end
10. Function FEASIBLE_SUB_SET()

11. if (sum+remSum≥ W) AND (sum == W )


or ( sum + w[i] + 1 <= W) then
return 0
end

12. return 1
13. First recursive call represents the case when the current item is selected, and hence the
problem size is reduced by w[i].

14. Second recursive call represents the case when we do not select the current item.

Program:

#include <stdio.h>
#include <stdlib.h>

#define ARRAYSIZE(a) (sizeof(a))/(sizeof(a[0]))

static int total_nodes;

// prints subset found


void printSubset(int A[], int size)
{
for(int i = 0; i < size; i++)
{
printf("%*d", 5, A[i]);
}
printf("\n");
}
// qsort compare function
int comparator(const void *pLhs, const void *pRhs)
{
int *lhs = (int *)pLhs;
int *rhs = (int *)pRhs;

return *lhs > *rhs;


}

// inputs
// s - set vector
// t - tuplet vector
// s_size - set size
// t_size - tuplet size so far
// sum - sum so far
// ite - nodes count
// target_sum - sum to be found
void subset_sum(int s[], int t[],
int s_size, int t_size,
int sum, int ite,
int const target_sum)
{
total_nodes++;

if( target_sum == sum )


{
// We found sum
printSubset(t, t_size);

// constraint check
if( ite + 1 < s_size && sum - s[ite] + s[ite+1] <= target_sum )
{
// Exclude previous added item and consider next candidate
subset_sum(s, t, s_size, t_size-1, sum - s[ite], ite + 1, target_sum);
}
return;
}
else
{
// constraint check
if( ite < s_size && sum + s[ite] <= target_sum )
{
// generate nodes along the breadth
for( int i = ite; i < s_size; i++ )
{
t[t_size] = s[i];

if( sum + s[i] <= target_sum )


{
// consider next level node (along depth)
subset_sum(s, t, s_size, t_size + 1, sum + s[i], i + 1, target_sum);
}
}
}
}
}

// Wrapper that prints subsets that sum to target_sum


void generateSubsets(int s[], int size, int target_sum)
{
int *tuplet_vector = (int *)malloc(size * sizeof(int));

int total = 0;

// sort the set


qsort(s, size, sizeof(int), &comparator);

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


{
total += s[i];
}

if( s[0] <= target_sum && total >= target_sum )


{

subset_sum(s, tuplet_vector, size, 0, 0, 0, target_sum);

free(tuplet_vector);
}

int main()
{
int weights[] = {15, 22, 14, 26, 32, 9, 16, 8};
int target = 53;

int size = ARRAYSIZE(weights);

generateSubsets(weights, size, target);

printf("Nodes generated %d\n", total_nodes);

return 0;
}

Output:

8 9 14 22
8 14 15 16
15 16 22
Nodes generated 68
15. Write a program to implement N Queens problem using Backtracking

The N Queen is the problem of placing N chess queens on an N×N chessboard so


that no two queens attack each other. For example, the following is a solution for
the 4 Queen problem.

Algorithm:
1. Initialize an empty chessboard of size NxN.
2. Start with the leftmost column and place a queen in the first row of that column.
3. Move to the next column and place a queen in the first row of that column.

4. Repeat step 3 until either all N queens have been placed or it is impossible to place a
queen in the current column without violating the rules of the problem.
5. If all N queens have been placed, print the solution.
6. If it is not possible to place a queen in the current column without violating the rules
of the problem, backtrack to the previous column.
7. Remove the queen from the previous column and move it down one row.
8. Repeat steps 4-7 until all possible configurations have been tried.

Program:

#define N 4
#include <stdbool.h>
#include <stdio.h>

/* A utility function to print solution */


void printSolution(int board[N][N])
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++)
printf(" %d ", board[i][j]);
printf("\n");
}
}

/* A utility function to check if a queen can


be placed on board[row][col]. Note that this
function is called when "col" queens are
already placed in columns from 0 to col -1.
So we need to check only left side for
attacking queens */
bool isSafe(int board[N][N], int row, int col)
{
int i, j;
/* Check this row on left side */
for (i = 0; i < col; i++)
if (board[row][i])
return false;

/* Check upper diagonal on left side */


for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
if (board[i][j])
return false;

/* Check lower diagonal on left side */


for (i = row, j = col; j >= 0 && i < N; i++, j--)
if (board[i][j])
return false;

return true;
}

/* A recursive utility function to solve N


Queen problem */
bool solveNQUtil(int board[N][N], int col)
{
/* base case: If all queens are placed
then return true */
if (col >= N)
return true;

/* Consider this column and try placing


this queen in all rows one by one */
for (int i = 0; i < N; i++) {
/* Check if the queen can be placed on
board[i][col] */
if (isSafe(board, i, col)) {
/* Place this queen in board[i][col] */
board[i][col] = 1;

/* recur to place rest of the queens */


if (solveNQUtil(board, col + 1))
return true;

/* If placing queen in board[i][col]


doesn't lead to a solution, then
remove queen from board[i][col] */
board[i][col] = 0; // BACKTRACK
}
}

/* If the queen cannot be placed in any row in


this column col then return false */
return false;
}
/* This function solves the N Queen problem using Backtracking. It mainly uses
solveNQUtil() to solve the problem. It returns false if queens cannot be placed,
otherwise, return true and prints placement of queens in the form of 1s.
Please note that there may be more than one solutions, this function prints one of the
feasible solutions.*/
bool solveNQ()
{
int board[N][N] = { { 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 } };

if (solveNQUtil(board, 0) == false) {
printf("Solution does not exist");
return false;
}

printSolution(board);
return true;
}

// driver program to test above function


int main()
{
solveNQ();
return 0;
}

Output:

0 0 1 0
1 0 0 0
0 0 0 1
0 1 0 0

You might also like