Lab Manual
Lab Manual
AIM:
To implement recursive and non-recursive algorithms for various functions and
study their order of growth from log2n to n!.
ALGORITHM:
1. Recursive Algorithm:
Base Case: If n is 0 or 1, return 1.
Recursive Case: Return n multiplied by the factorial of (n-1).
The algorithm is linear, takes the running time O(n).
2. Non-Recursive Algorithm:
Initialize a variable to 1.
Iterate from 1 to n, multiplying the current value by the iterator.
Iterator takes the running time O(mn)
PROGRAM:
#include <stdio.h>
int log2_recursive(int n) {
if (n <= 1) {
return 0;
} else {
return 1 + log2_recursive(n / 2);
}
}
int log2_nonrecursive(int n) {
int result = 0;
while (n > 1) {
n /= 2;
result++;
}
return result;
}
int main() {
int num = 16;
printf("Recursive log2: %d\n", log2_recursive(num));
printf("Non-Recursive log2: %d\n", log2_nonrecursive(num));
return 0;
}
OUTPUT:
Recursive log2: 4
Non – Recursive log2: 4
RESULT:
Thus, the recursive and non-recursive algorithms for various functions and study
their order of growth was implemented successfully.
EX.No:2 DIVIDE AND CONQUER – STRASSEN'S MATRIX
MULTIPLICATION
AIM:
To implement Strassen’s Matrix Multiplication using the Divide and Conquer
approach and demonstrate its application on directed acyclic graphs (DAGs).
ALGORITHM:
PROGRAM:
#include <stdio.h>
#define N 4
C[0][0] = M1 + M4 - M5 + M7;
C[0][1] = M3 + M5;
C[1][0] = M2 + M4;
C[1][1] = M1 - M2 + M3 + M6;
}
int main() {
int A[N][N] = {{1, 2}, {3, 4}};
int B[N][N] = {{5, 6}, {7, 8}};
int C[N][N];
strassen_multiply(A, B, C);
printf("Result:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%d ", C[i][j]);
}
printf("\n");
}
return 0;
}
OUTPUT:
19 22 832 832
43 50 832 832
832 832 832 832
0 0 256 0
RESULT:
Thus, the Strassen’s Matrix Multiplication using the Divide and Conquer
approach was implemented successfully.
EX.No:3 DECREASE AND CONQUER – TOPOLOGICAL
SORTING
AIM:
To implement Topological Sorting using the Decrease and Conquer approach in
Python and analyze its performance
ALGORITHM:
Topological Sorting is an ordering of vertices in a directed acyclic graph (DAG) such
that for every directed edge (u, v), vertex u comes before v in the ordering. The
objective is to find a topological ordering of the vertices.
1.Decrease and Conquer - Topological Sorting:
PROGRAM:
#include <stdio.h>
#include <stdlib.h>
struct Graph {
int vertices;
int adj[MAX][MAX];
};
int found = 0;
for (int i = 0; i < graph->vertices; i++) {
if (inDegree[i] == 0) {
printf("%d ", i); // Print the vertex
inDegree[i] = -1; // Mark it as processed
count++;
found = 1;
break;
}
}
if (!found) {
printf("Graph contains a cycle\n");
return;
}
}
printf("\n");
}
int main() {
int V = 6; // Number of vertices
struct Graph graph;
initGraph(&graph, V);
addEdge(&graph, 5, 2);
addEdge(&graph, 5, 0);
addEdge(&graph, 4, 0);
addEdge(&graph, 4, 1);
addEdge(&graph, 2, 3);
addEdge(&graph, 3, 1);
printf("Topological Sort:\n");
topologicalSort(&graph);
return 0;
}
OUTPUT:
Topological Sort:
542310
RESULT:
Thus, the Topological Sorting using the Decrease and Conquer approach was
implemented successfully.
EX.No:4 TRANSFORM AND CONQUER – HEAP SORT
AIM:
To implement Heap Sort using the Transform and Conquer approach in Python and
analyze performance.
ALGORITHM:
Heap Sort is a comparison-based sorting algorithm that uses a binary heap data
structure to build a max-heap (or min-heap) and then perform a heapbased sorting.
The objective is to sort an array in ascending (or descending) order.
Transform and Conquer - Heap Sort:
PROGRAM:
#include <stdio.h>
// Driver code
int main() {
int arr[] = {12, 11, 13, 5, 6, 7};
int n = sizeof(arr) / sizeof(arr[0]);
heapSort(arr, n);
printf("Sorted array: \n");
printArray(arr, n);
return 0;
}
Output:
Original array:
12 11 13 5 6 7
Sorted array:
5 6 7 11 12 13
RESULT:
Thus, the Heap Sort using the Transform and Conquer approach was implemented
successfully.
EX.No:5a DYNAMIC PROGRAMMING –
COIN CHANGE PROBLEM
AIM:
To implement the Coin Change Problem using dynamic programming approach in
Python.
ALGORITHM:
Given a set of coins and a target sum, the objective is to find the number of ways to
make the target sum using any combination of the given coins.
Program Logic:
1. Create a table to store the solutions to subproblems.
2. Initialize the table with base cases.
3. Fill in the table using the recurrence relation.
4. The final value in the table represents the solution to the original problem
PROGRAM:
#include <stdio.h>
int main() {
// Example coin denominations
int coins[] = {1, 2, 5};
int n = sizeof(coins) / sizeof(coins[0]);
// Target amount
int amount = 11;
return 0;
}
OUTPUT:
Number of ways to make change for 11:11
RESULT:
Thus, the Coin Change Problem using dynamic programming approach was
implemented successfully.
EX.No:5b DYNAMIC PROGRAMMING –
WARSHALL’S AND FLOYD’S ALGORITHM
AIM:
To implement the Warshall’s and Floyd’s Algorithm using dynamic programming
approach in Python.
ALGORITHM:
• Initialize the solution matrix same as the input graph matrix as a first step.
• Then update the solution matrix by considering all vertices as an intermediate
vertex.
• The idea is to pick all vertices one by one and updates all shortest paths which
include the picked vertex as an intermediate vertex in the shortest path.
• When we pick vertex number k as an intermediate vertex, we already have
considered vertices {0, 1, 2, .. k-1} as intermediate vertices.
• For every pair (i, j) of the source and destination vertices respectively, there are
two possible cases.
• k is not an intermediate vertex in shortest path from i to j. We keep the value of
dist[i][j] as it is.
• k is an intermediate vertex in shortest path from i to j. We update the value of
dist[i][j] as dist[i][k] + dist[k][j], if dist[i][j] > dist[i][k] + dist[k][j]
PROGRAM:
#include <stdio.h>
int main() {
/* Example graph represented as an adjacency matrix.
If there is no edge between two vertices, we use INF to represent the absence of
an edge.
*/
int graph[V][V] = {
{0, 5, INF, 10},
{INF, 0, 3, INF},
{INF, INF, 0, 1},
{INF, INF, INF, 0}
};
return 0;
}
OUTPUT:
The following matrix shows the shortest distance between every pair of vertices :
0 5 8 9
INF 0 3 4
INF INF 0 1
INF INF INF 0
RESULT:
Thus, the Warshall’s and Floyd’s Algorithm using dynamic programming approach
was implemented successfully.
EX.No:5c DYNAMIC PROGRAMMING – KNAPSACK
PROBLEM
AIM:
To implement the Knapsack Problem using dynamic programming approach in
Python.
ALGORITHM:
PROGRAM:
#include <stdio.h>
// Function to solve the knapsack problem using dynamic programming with space
optimization
int knapsack(int W, int w[], int v[], int n) {
int dp[W + 1];
return dp[W];
}
int main() {
int n = 3;
int w[] = {10, 20, 30};
int v[] = {60, 100, 120};
int W = 50;
return 0;
}
OUTPUT:
Maximum value in Knapsack=220
RESULT:
Thus, the Knapsack Problem using dynamic programming approach was
implemented successfully.
EX.No:6a GREEDY TECHNIQUE – DIJKSTRA‘S ALGORITHM
HUFFMAN TREE AND CODES
AIM:
To implement Dijkstra's Algorithm using Greedy Technique in Python for finding
the shortest path in a weighted graph.
ALGORITHM:
Given a weighted graph and a source vertex, the objective is to find the shortest path
from the source to all other vertices.
Program Logic:
1. Initialize the distance of all vertices from the source as infinity, and the distance of
the source vertex to itself as 0.
2. Create a priority queue to store vertices and their distances.
3. While the priority queue is not empty, extract the vertex with the minimum
distance.
4. Update the distances of adjacent vertices if a shorter path is found.
5. Repeat until all vertices are processed.
PROGRAM:
#include <stdio.h>
#include <limits.h>
#define V 6
visited[u] = 1;
int main() {
int graph[V][V] = {
{0, 2, 0, 6, 0, 0},
{2, 0, 3, 8, 5, 0},
{0, 3, 0, 0, 7, 0},
{6, 8, 0, 0, 9, 0},
{0, 5, 7, 9, 0, 1},
{0, 0, 0, 0, 1, 0}
};
dijkstra(graph, 0);
return 0;
}
OUTPUT:
Vertex Distance from Source
0 0
1 2
2 5
3 6
4 7
5 8
RESULT:
Thus, the Dijkstra's Algorithm using Greedy Technique was implemented
successfully.
EX.No:6b GREEDY TECHNIQUE – HUFFMAN TREE AND CODES
AIM:
To implement Huffman tree and codes using Greedy Technique in Python for
finding the shortest path in a weighted graph.
ALGORITHM:
Input is an array of unique characters along with their frequency of occurrences and
output is Huffman Tree.
1. Create a leaf node for each unique character and build a min heap of all leaf
nodes (Min Heap is used as a priority queue. The value of frequency field is used
to compare two nodes in min heap. Initially, the least frequent character is at root)
2. Extract two nodes with the minimum frequency from the min heap.
3. Create a new internal node with a frequency equal to the sum of the two nodes
frequencies. Make the first extracted node as its left child and the other extracted
node as its right child. Add this node to the min heap.
4. Repeat steps#2 and #3 until the heap contains only one node. The remaining node
is the root node and the tree is complete.
PROGRAM:
#include <stdio.h>
int main() {
int arr[] = {5, 9, 12, 13, 18, 20};
int n = sizeof(arr) / sizeof(arr[0]);
printHuffmanCodes(arr, n);
return 0;
}
OUTPUT:
Huffman Codes:
5 9 12 13 18 20
RESULT:
Thus, the Huffman tree and codes using Greedy Technique was implemented
successfully.
EX.No:7 ITREATIVE IMPROVEMENT – SIMPLEX METHOD
AIM:
To implement the Simplex Method using Iterative Improvement in Python for
solving linear programming problems.
ALGORITHM:
PROGRAM:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// Function prototypes
void simplexMethod(float tableau[MAX][MAX], int n, int m);
int findEnteringVariable(float tableau[MAX][MAX], int n, int m);
int findLeavingVariable(float tableau[MAX][MAX], int n, int m, int enteringVar);
void pivotOperation(float tableau[MAX][MAX], int n, int m, int enteringVar, int
leavingVar);
int main() {
int n, m;
float tableau[MAX][MAX];
printf("Enter the number of constraints (m): ");
scanf("%d", &m);
printf("Enter the number of variables (n): ");
scanf("%d", &n);
simplexMethod(tableau, n, m);
return 0;
}
printf("Final tableau:\n");
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
printf("%f\t", tableau[i][j]);
}
printf("\n");
}
// Check the last row (objective function row) for negative coefficients
for (int j = 0; j < n; j++) {
if (tableau[m][j] < minValue) {
minValue = tableau[m][j];
enteringVar = j;
}
}
return enteringVar;
}
return leavingVar;
}
OUTPUT:
Enter the number of constraints (m): 2
Enter the number of variables (n): 2
Enter the tableau (including the objective function row and constraints):
1114
2316
-3 -5 0 0
RESULT:
Thus, the Simplex Method using Iterative Improvement was implemented
successfully.
EX.No:8a BACKTRACKING – N-QUEEN PROBLEM
AIM:
To implement the N-Queen Problem using the Backtracking algorithm in Python.
ALGORITHM:
The N-Queen problem is to place N chess queens on an \(N \times N\) chessboard in
such a way that no two queens threaten each other.
1. Start with an empty chessboard.
2. Place queens one by one in different columns, starting from the leftmost column.
3. Check if the current placement is safe. If not, backtrack and try the next position.
4. Repeat the process until all queens are placed or it's determined that no solution
exists.
PROGRAM:
#include <stdio.h>
int board[8][8];
void printBoard() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (board[i][j] == 1)
printf("Q ");
else
printf(". ");
}
printf("\n");
}
}
if (solveNQ(row + 1))
return 1;
board[row][col] = 0;
}
}
return 0;
}
int main() {
solveNQ(0);
return 0;
}
OUTPUT:
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
Q . . . . . . .
RESULT:
Thus, the N-Queen Problem using the Backtracking algorithm was implemented
successfully.
EX.No:8b BACKTRACKING – SUBSET SUM PROBLEM
AIM:
To implement the Subset Sum Problem using the Backtracking algorithm in Python.
ALGORITHM:
Given a set of positive integers and a target sum, determine if there is a subset of the
set that adds up to the target sum.
1. Start with an empty subset.
2. Include an element in the subset and recursively check if the remaining sum can
be obtained.
3. Exclude the element from the subset and recursively check if the sum can be
obtained without the element.
4. Repeat the process for each element in the set.
PROGRAM:
#include <stdio.h>
int main() {
int set[] = {3, 34, 4, 12, 5, 2};
int sum = 9;
int n = sizeof(set) / sizeof(set[0]);
return 0;
}
OUTPUT:
Subset found
RESULT:
Thus, the Subset Sum Problem using the Backtracking algorithm was implemented
successfully.
EX.No:9a BRANCH AND BOUND – ASSIGNMENT PROBLEM
AIM:
To implement the Assignment Problem using the Branch and Bound algorithm in
Python.
ALGORITHM:
Given a set of cities and the distances between each pair of cities, find the shortest
possible tour that visits each city exactly once and returns to the starting city
1. Create a cost matrix for the assignment problem.
2. Implement the Branch and Bound algorithm to find the optimal assignment.
PROGRAM:
#include <stdio.h>
int cost[3][3] = {{10, 12, 15}, {8, 9, 12}, {7, 11, 10}};
int minCost = 100;
int main() {
assignment(0, 3, 0);
printf("Minimum cost: %d\n", minCost);
return 0;
}
OUTPUT:
Minimum cost : 25
RESULT:
Thus, the Assignment Problem using the Branch and Bound algorithm was
implemented successfully.
EX.No:9b BRANCH AND BOUND – TRAVELING SALESMAN
PROBLEM
AIM:
To implement the Traveling Salesman Problem using the Branch and Bound
algorithm in Python.
ALGORITHM:
Given a set of cities and the distances between each pair of cities, find the shortest
possible tour that visits each city exactly once and returns to the starting city.
1. Create a distance matrix for the TSP.
2. Implement the Branch and Bound algorithm to find the optimal tour.
PROGRAM:
#include <stdio.h>
int distance[4][4] = {{0, 10, 15, 20}, {10, 0, 35, 25}, {15, 35, 0, 30}, {20, 25, 30,
0}};
int minDistance = 1000;
int main() {
tsp(0, 4, 0);
printf("Minimum distance: %d\n", minDistance);
return 0;
}
OUTPUT:
Minimum Distance : 0
RESULT:
Thus, the Traveling Salesman Problem using the Branch and Bound algorithm was
implemented successfully.