CS3401 Algorithms Laboratory
CS3401 Algorithms Laboratory
Problem Statement:
Implementation of Linear Search.
Aim:
Determine the time required to search for an element using Linear search and 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.
Algorithm:
Step 1: Start
Step 2: Define a function linear_search(arr, x) that takes an array and a target element as
arguments and returns the index of the target element if it is present, or -1 if it is not.
Step 4: Repeat step 2 for different values of n, and store the average time taken for each value
of n in a list.
Step 5: Plot a graph of the average time taken versus n using a matplotlib library in python.
Step 6: Stop
Program:
import time
import matplotlib.pyplot as plt
def measure_time(n):
arr = list(range(n))
start_time = time.time()
linear_search(arr, n + 1)
return time.time() - start_time
n_values = [10, 100, 1000, 10000, 100000, 1000000]
times = [measure_time(n) for n in n_values]
plt.plot(n_values, times)
plt.xlabel('n (number of elements in the list)')
plt.ylabel('Time taken (seconds)')
plt.title('Linear Search Time Complexity')
plt.show()
Output:
Result:
Thus the above program has been implemented and verified successfully.
Ex. No. 2 Implementation of Recursive Binary Search
Problem Statement:
Implementation of Recursive Binary Search.
Aim:
Determine the time required to search for an element using Recursive Binary Search
and 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.
Algorithm:
Step 1: Start
Step 2: Define a function bin_search(arr, x, start, end) that returns the True if the target
element is present at mid, else it will search in the left or right of the mid element based on
mid.
Step 3: Define a function measure_time(arr, x) that measures the time taken to search for the
target element in the array using the time module in python.
Step 4: Repeat step 2 and store the average time taken for each value of list elements.
Step 5: Plot a graph of the average time taken versus n using a matplotlib library in python.
Step 6: Stop
Program:
import time
import matplotlib.pyplot as plt
val=[1,10,100,1000,10000,100000,1000000]
time_taken = [ ]
for n in val:
arr = list(range(n))
t = measure_time(arr, n // 2)
time_taken.append(t)
plt.plot(val, time_taken)
plt.xlabel('n (number of elements)')
plt.ylabel('Time taken (seconds)')
plt.show()
Output:
Result:
Thus the above program has been implemented and verified successfully.
Ex. No. 3 Implementation Naive String Matching algorithm
Problem Statement:
Implementation Naive String Matching algorithm.
Aim:
Write a function search (char pat [ ], char txt[ ]) that prints all occurrences of pat [ ] in
txt [ ] where a text txt [0...n-1] and a pattern pat [0...m-1] given, You may assume that n > m.
Algorithm:
Step 1: Start
Step 2: Define a function search(char pat[], char txt[]) using naive string matching that
checks how many times the pattern is present in the text.
Step 4: Stop
Program:
#include<stdio.h>
#include<string.h>
void search(char pat[], char txt[])
{
int m = strlen(pat);
int n = strlen(txt);
for (int i = 0; i <= n-m; i++)
{
int j=0;
while (j<m && pat[j]==txt[i+j])
j=j+1;
if (j == m)
printf("Pattern found at index %d\n", i);
}
}
int main()
{
char p[10]="BCD";
char t[10]="ABCDHBCD";
search(p,t);
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Ex. No. 4 Implementation of Insertion sort and Heap sort
Problem Statement:
Implementation of Insertion sort and Heap sort.
Aim:
Write a function to sort a given set of elements using the Insertion sort and Heap sort
methods 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.
Algorithm:
Step 1: Start
Step 2: Define a function insertion_sort(arr),
Step 2.1: If it is the first element, it is already sorted.
Step 2.2: Pick the next element and compare it with all elements in the sorted sub-list.
Step 2.3: Shift all the elements in the sorted sub-list that is greater than the value to be
Step 2.4: Insert the value and repeat until the list is sorted
Step 4: Define a function time_sorting that measures the time taken to sort the elements.
Step 5: Plot a graph of the average time taken versus n for insertion sort and heap sort using a
matplotlib library in python.
Step 6: Stop
Program:
import random
import time
import matplotlib.pyplot as plt
# Time the sorting process and return the elapsed time in seconds
def time_sorting(sort_func, arr):
start_time = time.time()
sort_func(arr)
end_time = time.time()
return end_time - start_time
Output:
Insertion Sort
Heap Sort
Result:
Thus the above program has been implemented, and verified successfully.
Ex. No. 5 Implementation of graph traversal using Breadth First Search
Problem Statement:
Implementation of graph traversal using Breadth First Search.
Aim:
To develop a program to implement graph traversal using Breadth First Search.
Algorithm:
Step 1: Start
Step 2: Declare a queue and visit the starting vertex and insert it into the Queue
Step 3: Visit all the non-visited adjacent vertices of the vertex which is in front of the Queue
and insert them into the Queue.
Step 4: When there is no new vertex to be visited from the vertex which is in front of the
Queue then delete that vertex.
Step 6: Stop
Program:
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTICES 100
int queue[MAX_VERTICES]; // queue used in BFS
int rear = -1, front = -1; // pointers for queue
int visited[MAX_VERTICES]; // array to mark visited vertices
int graph[MAX_VERTICES][MAX_VERTICES]; // adjacency matrix
int num_vertices; // number of vertices in the graph
// function to add an edge to the graph
void addEdge(int u, int v) {
graph[u][v] = 1;
graph[v][u] = 1;
}
// function to perform BFS
void bfs(int start) {
// mark the start vertex as visited and enqueue it
visited[start] = 1;
queue[++rear] = start;
while (front != rear) {
// dequeue a vertex from the queue
int current = queue[++front];
printf("%d ", current);
// check all the neighbors of the current vertex
for (int i = 0; i < num_vertices; i++) {
if (graph[current][i] == 1 && !visited[i]) {
visited[i] = 1;
queue[++rear] = i;
}
}
}
}
int main() {
// read the number of vertices in the graph
printf("Enter the number of vertices in the graph: ");
scanf("%d", &num_vertices);
// initialize the adjacency matrix
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
graph[i][j] = 0;
}
}
// read the edges of the graph
int num_edges;
printf("Enter the number of edges in the graph: ");
scanf("%d", &num_edges);
for (int i = 0; i < num_edges; i++) {
int u, v;
printf("Enter the endpoints of edge %d: ", i + 1);
scanf("%d %d", &u, &v);
addEdge(u, v);
}
// perform BFS starting from vertex 0
bfs(0);
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Ex. No. 6 Implementation of graph traversal using Depth First Search
Problem Statement:
Implementation of graph traversal using Depth First Search.
Aim:
To develop a program to implement graph traversal using Depth First Search.
Algorithm:
Step 1: Start
Step 2: Start by putting any one of the graph's vertices on top of a stack.
Step 3: Take the top item of the stack and add it to the visited list.
Step 4: 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.
Step 6: Stop
Program:
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTICES 100
int visited[MAX_VERTICES];
int graph[MAX_VERTICES][MAX_VERTICES];
int num_vertices;
void addEdge(int u, int v) {
graph[u][v] = 1;
graph[v][u] = 1;
}
void dfs(int current) {
visited[current] = 1;
printf("%d ", current);
for (int i = 0; i < num_vertices; i++) {
if (graph[current][i] == 1 && !visited[i]) {
dfs(i);
}
}
}
int main() {
printf("Enter the number of vertices in the graph: ");
scanf("%d", &num_vertices);
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
graph[i][j] = 0;
}
}
int num_edges;
printf("Enter the number of edges in the graph: ");
scanf("%d", &num_edges);
for (int i = 0; i < num_edges; i++) {
int u, v;
printf("Enter the endpoints of edge %d: ", i + 1);
scanf("%d %d", &u, &v);
addEdge(u, v);
}
dfs(0);
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Ex. No. 7 Implementation of Dijkstra’s algorithm
Problem Statement:
Implementation of Dijkstra’s algorithm.
Aim:
To develop a program to find the shortest paths from a given vertex to other vertices in
a weighted connected graph using Dijkstra’s algorithm.
Algorithm:
Step 1: Start
Step 2: Create a 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.
Step 3: 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.
Step 4: While the shortest-path tree set doesn’t include all vertices
Step 4.1: Pick a vertex u that is not there in the shortest-path tree set and has a minimum
distance value.
Step 4.3: Then update the distance value of all adjacent vertices of u. 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.
Step 5: Stop
Program:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_VERTICES 100
int graph[MAX_VERTICES][MAX_VERTICES];
int distance[MAX_VERTICES];
int visited[MAX_VERTICES];
int num_vertices;
int num_edges;
void addEdge(int u, int v, int weight) {
graph[u][v] = weight;
graph[v][u] = weight;
}
int minDistance() {
int min = INT_MAX, min_index;
for (int v = 0; v < num_vertices; v++) {
if (!visited[v] && distance[v] <= min) {
min = distance[v];
min_index = v;
}
}
return min_index;
}
void printPaths(int start) {
printf("Vertex\tDistance from %d\n", start);
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Ex. No. 8 Implementation of Prim’s algorithm
Problem Statement:
Implementation of Prim’s algorithm.
Aim:
To find the minimum cost spanning tree of a given undirected graph using Prim’s
algorithm.
Algorithm:
Step 1: Start
Step 2: Determine an arbitrary vertex as the starting vertex of the Minimum Spanning Tree
(MST).
Step 3: Follow steps 4 to 6 till there are vertices that are not included in the MST (known as
fringe vertex).
Step 4: Find edges connecting any tree vertex with the fringe vertices.
Step 6: Add the chosen edge to the MST if it does not form any cycle.
Step 8: Stop
Program:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_VERTICES 100
int graph[MAX_VERTICES][MAX_VERTICES];
int parent[MAX_VERTICES];
int key[MAX_VERTICES];
int visited[MAX_VERTICES];
int num_vertices;
int minKey() {
int min = INT_MAX, min_index;
for (int v = 0; v < num_vertices; v++) {
if (!visited[v] && key[v] < min) {
min = key[v];
min_index = v;
}
}
return min_index;
}
void printMST() {
printf("Edge\tWeight\n");
for (int v = 1; v < num_vertices; v++) {
printf("%d - %d\t%d\n", parent[v], v, graph[v][parent[v]]);
}
}
void prim() {
for (int v = 0; v < num_vertices; v++) {
key[v] = INT_MAX;
visited[v] = 0;
}
key[0] = 0;
parent[0] = -1;
for (int count = 0; count < num_vertices - 1; count++) {
int u = minKey();
visited[u] = 1;
for (int v = 0; v < num_vertices; v++) {
if (graph[u][v] && !visited[v] && graph[u][v] < key[v]) {
parent[v] = u;
key[v] = graph[u][v];
}
}
}
printMST();
}
int main() {
printf("Enter the number of vertices in the graph: ");
scanf("%d", &num_vertices);
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
graph[i][j] = 0;
}
}
int num_edges;
printf("Enter the number of edges in the graph: ");
scanf("%d", &num_edges);
for (int i = 0; i < num_edges; i++) {
int u, v, weight;
printf("Enter the endpoints and weight of edge %d: ", i + 1);
scanf("%d %d %d", &u, &v, &weight);
graph[u][v] = weight;
graph[v][u] = weight;
}
prim();
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Ex. No. 9 Implementation of Floyd’s algorithm
Problem Statement:
Implementation of Floyd’s algorithm for the All-Pairs- Shortest-Paths problem.
Aim:
To Implement Floyd’s algorithm for the All-Pairs- Shortest-Paths problem.
Algorithm:
Step 1: Start
Step 2: Initialize the solution matrix same as the input graph matrix as a first step.
Step 3: Then update the solution matrix by considering all vertices as an intermediate vertex.
Step 4: Pick all vertices one by one and update all shortest paths which include the picked
vertex as an intermediate vertex in the shortest path.
Step 5: When we pick vertex number k as an intermediate vertex, we already have considered
vertices {0, 1, 2, .. k-1} as intermediate vertices.
Step 6: For every pair (i, j) of the source and destination vertices respectively, there are two
possible cases.
Step 6.1: k is not an intermediate vertex in shortest path from i to j. We keep the value
of dist[i][j] as it is.
Step 6.2: 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]
Step 7: Stop
Program:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_VERTICES 100
int graph[MAX_VERTICES][MAX_VERTICES];
int dist[MAX_VERTICES][MAX_VERTICES];
int num_vertices;
void floyd() {
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
dist[i][j] = graph[i][j];
}
}
for (int k = 0; k < num_vertices; k++) {
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX && dist[i][k] + dist[k][j]
< dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
}
int main() {
printf("Enter the number of vertices in the graph: ");
scanf("%d", &num_vertices);
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
if (i==j)
graph[i][j] =0;
else
graph[i][j] = INT_MAX;
}
}
int num_edges;
printf("Enter the number of edges in the graph: ");
scanf("%d", &num_edges);
for (int i = 0; i < num_edges; i++) {
int u, v, weight;
printf("Enter the endpoints and weight of edge %d: ", i + 1);
scanf("%d %d %d", &u, &v, &weight);
graph[u][v] = weight;
}
floyd();
printf("Shortest distances between pairs of vertices:\n");
for (int i = 0; i < num_vertices; i++) {
for (int j = 0; j < num_vertices; j++) {
if (dist[i][j] == INT_MAX) {
printf("INF\t");
} else {
printf("%d\t", dist[i][j]);
}
}
printf("\n");
}
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Computation of transitive closure of a given directed graph
Ex. No. 10
using Warshall's algorithm
Problem Statement:
Compute the transitive closure of a given directed graph using Warshall's algorithm.
Aim:
To compute the transitive closure of a given directed graph using Warshall's algorithm.
Algorithm:
Step 1: Start
Step 2: Take adjacency matrix as input for graph G, say ‘graph[V][V]’ where graph[i][j] is 1
if there is an edge from vertex i to vertex j or i is equal to j, otherwise graph[i][j] is 0.
Step 3: Initialize the solution matrix the same as the input graph adjacency matrix.
Step 4: For finding transitive closure, If vertex k is on a path from i to j, then make sure that
the value of solution matrix (closure[i][j]) is 1, (where closure[i][j] = closure[i][j] ||
(closure[i][k] && closure[k][j])).
Step 5: Stop
Program:
#include <stdio.h>
#define MAX 100
void warshall(int n, int graph[MAX][MAX], int closure[MAX][MAX]) {
int i, j, k;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
closure[i][j] = graph[i][j];
} }
for (k = 0; k < n; k++) {
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
closure[i][j] = closure[i][j] || (closure[i][k] && closure[k][j]);
} } }
}
int main() {
int n, i, j, graph[MAX][MAX], closure[MAX][MAX];
printf("Enter the number of nodes in the graph: ");
scanf("%d", &n);
printf("Enter the adjacency matrix of the graph:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
scanf("%d", &graph[i][j]);
} }
warshall(n, graph, closure);
printf("The transitive closure of the graph is:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if(i == j)
printf("1 ");
else
printf("%d ", closure[i][j]);
}
printf("\n");
}
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Computation of maximum and minimum numbers in a given
Ex. No. 11
list of n numbers using the divide and conquer technique
Problem Statement:
Compute maximum and minimum numbers in a given list of n numbers using the
divide and conquer technique.
Aim:
To develop a program to find out the maximum and minimum numbers in a given list
of n numbers using the divide and conquer technique.
Algorithm:
Step 1: Start
Step 2: Divide and conquer approach divides array into two halves and easily maximum and
minimum numbers in each halves are found. Later, it returns the maximum of two maxima of
each half and the minimum of two minima of each half.
Step 3: Stop
Program:
#include <stdio.h>
void max_min(int arr[], int left, int right, int *max, int *min) {
if (left == right) {
*max = arr[left];
*min = arr[left];
return;
}
int mid = (left + right) / 2;
int max1, min1, max2, min2;
max_min(arr, left, mid, &max1, &min1);
max_min(arr, mid + 1, right, &max2, &min2);
*max = (max1 > max2) ? max1 : max2;
*min = (min1 < min2) ? min1 : min2;
}
int main() {
int n, arr[100], i, max, min;
printf("Enter the number of elements: ");
scanf("%d", &n);
printf("Enter the array elements:\n");
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
max_min(arr, 0, n - 1, &max, &min);
printf("The maximum element is %d\n", max);
printf("The minimum element is %d\n", min);
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Implementation of Merge sort and Quick sort methods to sort
Ex. No. 12
an array of elements
Problem Statement:
Implementation of Merge sort and Quick sort methods to sort an array of elements.
Aim:
To implement Merge sort and Quick sort methods to sort an array of elements and
determine the time required to sort. 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.
Algorithm:
Step 1: Start
Step 2: For mergesort, divide array into two array of equal size and keep on dividing it until
one element is left in each array.
Step 3: Keep merging the sub arrays to produce sorted arrays until there is only one array
remaining. This will be our sorted array.
Step 4: For quicksort, divide array into subarrays by selecting a pivot element (first element
selected from the array).
Step 5: While dividing the array, the pivot element should be positioned in such a way that
elements less than pivot are kept on the left side and elements greater than pivot are on the
right side of the pivot.
Step 6: The left and right subarrays are also divided using the same approach. This process
continues until each subarray contains a single element.
Step 7: At this point, elements are already sorted. Finally, elements are combined to form a
sorted array.
Step 8: Define a function measure_time that measures the time taken to sort the elements.
Step 9: Plot a graph of the average time taken versus n for Merge sort and Quick sort using a
matplotlib library in python.
Program:
import random
import time
import matplotlib.pyplot as plt
def merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
left_half = arr[:mid]
right_half = arr[mid:]
merge_sort(left_half)
merge_sort(right_half)
i=j=k=0
while i < len(left_half) and j < len(right_half):
if left_half[i] < right_half[j]:
arr[k] = left_half[i]
i += 1
else:
arr[k] = right_half[j]
j += 1
k += 1
while i < len(left_half):
arr[k] = left_half[i]
i += 1
k += 1
while j < len(right_half):
arr[k] = right_half[j]
j += 1
k += 1
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[0]
less_than_pivot = []
greater_than_pivot = []
equal_to_pivot = []
for elem in arr:
if elem < pivot:
less_than_pivot.append(elem)
elif elem > pivot:
greater_than_pivot.append(elem)
else:
equal_to_pivot.append(elem)
return quick_sort(less_than_pivot) + equal_to_pivot + quick_sort(greater_than_pivot)
def generate_random_list(n):
return [random.randint(1, 100000) for i in range(n)]
def measure_time(sort_func, arr):
start_time = time.time()
sort_func(arr)
end_time = time.time()
return end_time - start_time
n_values = [100, 1000, 5000, 10000, 20000]
merge_sort_times = []
quick_sort_times = []
for n in n_values:
arr = generate_random_list(n)
merge_sort_time = measure_time(merge_sort, arr.copy())
quick_sort_time = measure_time(quick_sort, arr.copy())
merge_sort_times.append(merge_sort_time)
quick_sort_times.append(quick_sort_time)
plt.plot(n_values, merge_sort_times, label='Merge Sort')
plt.plot(n_values, quick_sort_times, label='Quick Sort')
plt.xlabel('Number of elements in the list')
plt.ylabel('Time taken to sort (in seconds)')
plt.legend()
plt.show()
Output:
Result:
Thus the above program has been implemented, and verified successfully
Ex. No. 13 Implementation of N Queens problem using Backtracking
Problem Statement:
Implement N Queens problem using Backtracking.
Aim:
To implement N Queens problem using Backtracking.
Algorithm:
Step 1: Start
Step 3: Start with the leftmost column and place a queen in the first row of that column.
Step 4: Move to the next column and place a queen in the first row of that column.
Step 5: Repeat step 4 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.
Step 7: 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.
Step 8: Remove the queen from the previous column and move it down one row.
Step 9: Repeat steps 5-8 until all possible configurations have been tried.
Program:
#include <stdio.h>
int is_valid(int board[][100], int row, int col, int n) {
// check for any queen in the same column
for (int i = 0; i < row; i++) {
if (board[i][col] == 1) {
return 0;
}
}
// check for any queen in the diagonal
int i = row - 1, j = col - 1;
while (i >= 0 && j >= 0) {
if (board[i][j] == 1) {
return 0;
}
i--, j--;
}
// check for any queen in the other diagonal
i = row - 1, j = col + 1;
while (i >= 0 && j < n) {
if (board[i][j] == 1) {
return 0;
}
i--, j++;
}
// the position is valid
return 1;
}
void backtrack(int board[][100], int row, int n, int *count) {
// base case: we have placed all queens
if (row == n) {
// print the solution
printf("Solution %d:\n", *count);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%c ", board[i][j] ? 'Q' : '.');
}
printf("\n");
}
printf("\n");
// increment the count of solutions
(*count)++;
return;
}
// try placing a queen in each column of the current row
for (int col = 0; col < n; col++) {
if (is_valid(board, row, col, n)) {
board[row][col] = 1;
backtrack(board, row+1, n, count);
board[row][col] = 0;
}
}
}
void solve_n_queens(int n) {
int board[100][100] = {0};
int count = 1;
backtrack(board, 0, n, &count);
}
int main() {
int n;
printf("Enter the value of N: ");
scanf("%d", &n);
printf("\n");
solve_n_queens(n);
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Ex. No. 14 Implementation of Traveling Salesperson problem
Problem Statement:
Implementation of Traveling Salesperson problem.
Aim:
To implement branch and bound scheme to find the optimal solution for the Traveling
Salesperson problem and then solve the same problem instance using any approximation
algorithm and determine the error in the approximation.
Algorithm:
Step 1: Start
Step 2: For Branch and bound approach, Initialize the current best solution as infinity and the
current path as an empty path.
Step 3: Create a priority queue to store partial solutions with their lower bound estimates as
priorities.
Step 4: Insert the initial partial solution, which consists of a single starting node and an empty
set of visited nodes, into the priority queue with its lower bound estimate as the distance from
the starting node to the nearest unvisited node.
Step 5.1: Extract the partial solution with the lowest priority from the priority queue.
Step 5.2: If the lower bound estimate of the partial solution is worse than the current
best solution, discard the partial solution and move on to the next one in the priority
queue.
Step 5.3: If the partial solution is a complete path that visits all nodes, update the current
best solution if it is better than the previous best solution.
Step 5.4: Otherwise, for each unvisited node that can be reached from the last node in
the partial solution, create a new partial solution by adding the node to the end of the
path and updating the set of visited nodes. Compute the lower bound estimate of the
new partial solution as the sum of the distances of the remaining unvisited nodes to their
nearest neighbor plus the distance from the last node in the path to the new node. Insert
the new partial solution into the priority queue only if its lower bound estimate is better
than the current best solution.
Step 6: For Nearest neighbour approximation, mark the starting node as visited.
Step 8: Add the distance from the last visited node to the starting node to the total distance
traveled.
Step 9: Compute the error as the ratio of the total distance traveled by the approximate
solution to the Branch and Bound optimal solution.
Step 10: Return the path, the total distance traveled, and the error.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include <math.h>
#define N 5
int dist[N][N] = {
{ 0, 3, 4, 2, 7 },
{ 3, 0, 4, 6, 3 },
{ 4, 4, 0, 5, 8 },
{ 2, 6, 5, 0, 6 },
{ 7, 3, 8, 6, 0 }
};
int path[N + 1];
bool visited[N] = { false };
int best_path[N + 1];
int best_length = INT_MAX;
int compute_lower_bound(int curr_node)
{
int lb = 0;
for (int i = 0; i < curr_node; i++) {
lb += dist[path[i]][path[i + 1]];
}
int min_outgoing = INT_MAX;
for (int i = curr_node; i < N; i++) {
if (!visited[i]) {
int min_dist = INT_MAX;
for (int j = 0; j < N; j++) {
if (dist[i][j] < min_dist) {
min_dist = dist[i][j];
}
}
min_outgoing = (min_outgoing < min_dist) ? min_outgoing : min_dist;
}
}
lb += min_outgoing;
return lb;
}
void explore(int curr_node, int curr_length)
{
if (curr_node == N) {
curr_length += dist[path[N - 1]][path[0]];
if (curr_length < best_length) {
best_length = curr_length;
for (int i = 0; i <= N; i++) {
best_path[i] = path[i];
}
}
return;
}
for (int i = 1; i < N; i++) {
if (!visited[i]) {
path[curr_node] = i;
visited[i] = true;
int lb = compute_lower_bound(curr_node);
if (curr_length + lb < best_length) {
explore(curr_node + 1, curr_length + dist[path[curr_node - 1]][i]);
}
visited[i] = false;
}
}
}
void tsp_branch_and_bound()
{
visited[0] = true;
path[0] = 0;
explore(1, 0);
}
void print_path()
{
printf("Optimal path using Branch and Bound: ");
for (int i = 0; i <= N; i++) {
printf("%d ", best_path[i]);
}
printf("\n");
printf("Length: %d\n", best_length);
}
void tsp_nearest_neighbor()
{
visited[0] = true;
path[0] = 0;
for (int i = 1; i < N; i++) {
int nearest = -1;
int min_dist = INT_MAX;
for (int j = 0; j < N; j++) {
if (!visited[j] && dist[path[i - 1]][j] < min_dist) {
min_dist = dist[path[i - 1]][j];
nearest = j;
}
}
path[i] = nearest;
visited[nearest] = true;
}
path[N] = 0;
}
double calculate_path_length()
{
double length = 0.0;
for (int i = 0; i < N; i++) {
int curr_node = path[i];
int next_node = path[i + 1];
length += dist[curr_node][next_node];
}
return length;
}
void print_app_path()
{
printf("\nOptimal path using Approximation: ");
for (int i = 0; i <= N; i++) {
printf("%d ", path[i]);
}
printf("\n");
}
int main()
{
tsp_branch_and_bound();
print_path();
tsp_nearest_neighbor();
double approx_length = calculate_path_length();
print_app_path();
printf("Length: %lf\n", approx_length);
printf("\nApproximation error: %.2f%%\n", 100.0 * (approx_length - best_length) /
best_length);
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.
Implementation of randomized algorithm for finding the kth
Ex. No. 15
smallest number.
Problem Statement:
Implement randomized algorithm for finding the kth smallest number.
Aim:
To implement randomized algorithm for finding the kth smallest number.
Algorithm:
Step 1: Start
Step 2: Create a function called randomizedSelect that takes an array arr, its leftmost and
rightmost indices l and r, and the value of k representing the rank of the element we want to
find.
Step 3: If the array has only one element (i.e., l == r), return that element.
Step 4: Call the randomizedPartition function to partition the array randomly and return the
index of the pivot element.
Step 5: Calculate the rank pivotRank of the pivot element by subtracting l from the pivot
index and adding 1.
Step 7: If k is less than pivotRank, recursively call randomizedSelect on the left subarray
with l, pivotIndex - 1, and k as the arguments.
Step 8: If k is greater than pivotRank, recursively call randomizedSelect on the right subarray
with pivotIndex + 1, r, and k - pivotRank as the arguments.
Step 9: Create a function called randomizedPartition that takes an array arr, its leftmost and
rightmost indices l and r, and partitions the array randomly by:
Step 9.2: Swapping the element at index i with the element at index r.
Step 9.3: Returning the index of the pivot element after partitioning the array with the
partition function.
Step 10: Create a function called partition that takes an array arr, its leftmost and rightmost
indices l and r, and partitions the array by:
Step 10.1: Choosing the last element pivot as the pivot element.
Step 10.3: Looping through each element arr[j] in the subarray from index l to r - 1.
Step 10.4: If arr[j] is less than or equal to pivot, increment i and swap arr[i] with arr[j].
Program:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Function to swap two elements in an array
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
// Function to partition an array and return the index of the pivot element
int partition(int arr[], int l, int r) {
int pivot = arr[r]; // choose the last element as the pivot
int i = l - 1; // initialize i to be the index before the leftmost element
for (int j = l; j <= r - 1; j++) {
if (arr[j] <= pivot) {
i++; // increment i
swap(&arr[i], &arr[j]); // swap arr[i] and arr[j]
}
}
swap(&arr[i + 1], &arr[r]); // swap arr[i + 1] and arr[r] to place the pivot element in its
correct position
return i + 1; // return the index of the pivot element
}
// Function to partition an array randomly and return the index of the pivot element
int randomizedPartition(int arr[], int l, int r) {
srand(time(NULL)); // initialize the random number generator with the current time
int i = rand() % (r - l + 1) + l; // generate a random index between l and r
swap(&arr[i], &arr[r]); // swap the element at index i with the element at index r
return partition(arr, l, r); // partition the array and return the index of the pivot element
}
// Function to find the kth smallest element in an array using the randomized algorithm
int randomizedSelect(int arr[], int l, int r, int k) {
if (l == r) { // if the array has only one element
return arr[l];
}
int pivotIndex = randomizedPartition(arr, l, r); // partition the array randomly and return
the index of the pivot element
int pivotRank = pivotIndex - l + 1; // calculate the rank of the pivot element
if (k == pivotRank) { // if the rank of the pivot element is equal to k
return arr[pivotIndex]; // return the pivot element
}
else if (k < pivotRank) { // if k is less than the rank of the pivot element
return randomizedSelect(arr, l, pivotIndex - 1, k); // recursively call randomizedSelect
on the left subarray
}
else { // if k is greater than the rank of the pivot element
return randomizedSelect(arr, pivotIndex + 1, r, k - pivotRank); // recursively call
randomizedSelect on the right subarray
}
}
// Driver code
int main() {
int arr[] = {6, 1, 8, 4, 9, 2};
int n = sizeof(arr) / sizeof(arr[0]);
int k = 3; // find the 3rd smallest element
int kthSmallest = randomizedSelect(arr, 0, n - 1, k);
printf("The %dth smallest element is %d\n", k, kthSmallest);
return 0;
}
Output:
Result:
Thus the above program has been implemented, and verified successfully.