0% found this document useful (0 votes)
10 views42 pages

AOA Lab Manual

The document is a laboratory manual for Computer Engineering students focusing on algorithm analysis, detailing various sorting and searching algorithms such as Selection Sort, Insertion Sort, Merge Sort, and Binary Search, along with Dijkstra's algorithm for finding the shortest path. Each experiment includes aims, theoretical explanations, algorithms, C programming implementations, and outputs. The manual serves as a practical guide for students to implement and understand these algorithms in a hands-on manner.

Uploaded by

rahulrjaiswar15
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views42 pages

AOA Lab Manual

The document is a laboratory manual for Computer Engineering students focusing on algorithm analysis, detailing various sorting and searching algorithms such as Selection Sort, Insertion Sort, Merge Sort, and Binary Search, along with Dijkstra's algorithm for finding the shortest path. Each experiment includes aims, theoretical explanations, algorithms, C programming implementations, and outputs. The manual serves as a practical guide for students to implement and understand these algorithms in a hands-on manner.

Uploaded by

rahulrjaiswar15
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 42

A Laboratory Manual

For
Analysis of Algorithm
Semester IV
Computer Engineering
(2024-25)
List of Experiment

1) To implement the Selection sort, Insertion sort.


2) Write a program to implement Merge sort & Binary search.
3) Write a program to find Single source shortest path- Dijkstra using greedy method
approach.
4) Write a program to find all pair shortest path-Floyd Warshall.
5) Write a program to implement travelling salesperson problem using Dynamic
programming.
6) Write a program to find Longest common subsequence using Dynamic programming.
7) Write a program to find N-queen problem using Backtracking and Branch and bound.
8) Write a program to find the Naïve string matching algorithms.
9) Write a program to find the Knuth Morris Pratt algorithm.
10) Write a program to find the Rabin Karp algorithm.
Experiment No 1
Aim: To implement the Selection sort, Insertion sort.
Theory: Selection sort

Selection sort is a simple and efficient sorting algorithm that works by repeatedly selecting
the smallest (or largest) element from the unsorted portion of the list and moving it to the
sorted portion of the list.
The algorithm repeatedly selects the smallest (or largest) element from the unsorted portion
of the list and swaps it with the first element of the unsorted part. This process is repeated
for the remaining unsorted portion until the entire list is sorted.
Selection Sort Algorithm in C
selectionSort(array, size)
loop i from 0 to size - 2
set minIndex as i
loop j from first unsorted to size - 1
check if array[j] < array[minIndex]
set minIndex as j
swap array[i] with array[minIndex]
end for
end selectionSort

Complexity Analysis of Selection Sort


Time Complexity: The time complexity of Selection Sort is O(N2) as there are two nested
loops:
 One loop to select an element of Array one by one = O(N)
 Another loop to compare that element with every other Array element = O(N)
 Therefore overall complexity = O(N) * O(N) = O(N*N) = O(N2)
Auxiliary Space: O(1) as the only extra memory used is for temporary variables while
swapping two values in Array. The selection sort never makes more than O(N) swaps and
can be useful when memory writing is costly.
Program

// C program for implementation of selection sort


#include <stdio.h>
void selectionSort(int arr[], int N) {
for (int i = 0; i < N - 1; i++) {
int min_idx = i;
for (int j = i + 1; j < N; j++) {
if (arr[j] < arr[min_idx]) {
min_idx = j;
}
}
int temp = arr[min_idx];
arr[min_idx] = arr[i];
arr[i] = temp;
}
}
int main() {
int arr[] = {64, 25, 12, 22, 11};
int N = sizeof(arr) / sizeof(arr[0]);
printf("Unsorted array: \n");
for (int i = 0; i < N; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// Calling selection sort
selectionSort(arr, N);

printf("Sorted array: \n");


for (int i = 0; i < N; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}

Output
Unsorted array:
64 25 12 22 11
Sorted array:
11 12 22 25 64
Insertion Sort

Insertion sort is a simple sorting algorithm that works similarly to the way you sort
playing cards in your hands. The array is virtually split into a sorted and an unsorted part.
Values from the unsorted part are picked and placed in the correct position in the sorted
part.

Algorithm

The simple steps of achieving the insertion sort are listed as follows -

Step 1 - If the element is the first element, assume that it is already sorted. Return 1.

Step2 - Pick the next element, and store it separately in a key.

Step3 - Now, compare the key with all elements in the sorted array.

Step 4 - If the element in the sorted array is smaller than the current element, then move to
the next element. Else, shift greater elements in the array towards the right.

Step 5 - Insert the value.

Step 6 - Repeat until the array is sorted.

Time Complexity: O(N^2)


Auxiliary Space: O(1)
Program

// C program for insertion sort


#include <math.h>
#include <stdio.h>

void insertionSort(int arr[], int N) {

// Starting from the second element


for (int i = 1; i < N; i++) {
int key = arr[i];
int j = i - 1;

// Move elements of arr[0..i-1], that are


// greater than key, to one position to
// the right of their current position
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}

// Move the key to its correct position


arr[j + 1] = key;
}
}

int main() {
int arr[] = { 12, 11, 13, 5, 6 };
int N = sizeof(arr) / sizeof(arr[0]);

printf("Unsorted array: ");


for (int i = 0; i < N; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// Calling insertion sort on array arr
insertionSort(arr, N);

printf("Sorted array: ");


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

return 0;
}

Output

Unsorted array: 12 11 13 5 6
Sorted array: 5 6 11 12 13

Conclusion: Thus we have studied about Selection sort and Insertion sort.
Experiment No 2

Aim: Write a program to implement Merge sort & Binary search.


Theory: Merge sort
Merge sort is defined as a sorting algorithm that works by dividing an array into smaller
subarrays, sorting each subarray, and then merging the sorted subarrays back together to
form the final sorted array.
In simple terms, we can say that the process of merge sort is to divide the array into two
halves, sort each half, and then merge the sorted halves back together. This process is
repeated until the entire array is sorted.

Algorithm:
Step 1: Start
Step 2: Declare an array and left, right, mid variable
Step 3: Perform merge function.
mergesort(array,left,right)
mergesort (array, left, right)
if left > right
return
mid= (left+right)/2
mergesort(array, left, mid)
mergesort(array, mid+1, right)
merge(array, left, mid, right)
Step 4: Stop
Program
// C program for Merge Sort //
#include <stdio.h>
#include <stdlib.h>
void merge(int arr[], int left, int mid, int right) {
int i, j, k;
int n1 = mid - left + 1;
int n2 = right - mid;
int leftArr[n1], rightArr[n2];
for (i = 0; i < n1; i++)
leftArr[i] = arr[left + i];
for (j = 0; j < n2; j++)
rightArr[j] = arr[mid + 1 + j];
i = 0;
j = 0;
k = left;
while (i < n1 && j < n2) {
if (leftArr[i] <= rightArr[j]) {
arr[k] = leftArr[i];
i++;
}
else {
arr[k] = rightArr[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = leftArr[i];
i++;
k++;
}

while (j < n2) {


arr[k] = rightArr[j];
j++;
k++;
}
}
void mergeSort(int arr[], int left, int right) {
if (left < right) {
// Calculate the midpoint
int mid = left + (right - left) / 2;

// Sort first and second halves


mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);

// Merge the sorted halves


merge(arr, left, mid, right);
}
}

int main() {
int arr[] = { 12, 11, 13, 5, 6, 7 };
int n = sizeof(arr) / sizeof(arr[0]);

// Sorting arr using mergesort


mergeSort(arr, 0, n - 1);

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


printf("%d ", arr[i]);
return 0;
}

Output

5 6 7 11 12 13
Binary Search

A quick method for locating a particular element in a sorted array is a binary search. The initial
task of this algorithm is to compare the target value to the array's middle element. The search
is deemed successful if the target value is contained in the middle element. The algorithm will
look in the left half of the array if the goal value is less than the centre element. The programme
will scan the right half of the array if the goal value is greater than the centre element. This
method is repeated until either the goal value or the search range is exhausted.

Binary Search Algorithm

Step 1 − Select the middle item in the array and compare it with the key value to be searched.
If it is matched, return the position of the median.

Step 2 − If it does not match the key value, check if the key value is either greater than or less
than the median value.

Step 3 − If the key is greater, perform the search in the right sub-array; but if the key is lower
than the median value, perform the search in the left sub-array.

Step 4 − Repeat Steps 1, 2 and 3 iteratively, until the size of sub-array becomes 1.

Step 5 − If the key value does not exist in the array, then the algorithm returns an
unsuccessful search.
Program
#include <stdio.h>
int binarySearch(int array[], int x, int low, int high) {
// Repeat until the pointers low and high meet each other
while (low <= high) {
int mid = low + (high - low) / 2;

if (x == array[mid])
return mid;

if (x > array[mid])
low = mid + 1;

else
high = mid - 1;
}

return -1;
}

int main(void) {
int array[] = {3, 4, 5, 6, 7, 8, 9};
int n = sizeof(array) / sizeof(array[0]);
int x = 4;
int result = binarySearch(array, x, 0, n - 1);
if (result == -1)
printf("Not found");
else
printf("Element is found at index %d", result);
return 0;
}

Output
Element is found at index 1

Conclusion: Thus we have studied about Merge sort and Binary search.
Experiment No 3

Aim: Write a program to find Single source shortest path- Dijkstra using greedy method
approach.

Theory: Dijkstra Algorithm

The algorithm maintains a set of visited vertices and a set of unvisited vertices. It starts at
the source vertex and iteratively selects the unvisited vertex with the smallest tentative
distance from the source. It then visits the neighbours of this vertex and updates their
tentative distances if a shorter path is found. This process continues until the destination
vertex is reached, or all reachable vertices have been visited.
Algorithm for Dijkstra’s Algorithm:

Algorithm: Dijkstra’s-Algorithm (G, w, s)

for each vertex v Є G.V

v.d := ∞

v.∏ := NIL

s.d := 0

S := Ф

Q := G.V

while Q ≠ Ф

u := Extract-Min (Q)

S := S U {u}

for each vertex v Є G.adj[u]

if v.d > u.d + w(u, v)

v.d := u.d + w(u, v)

v.∏ := u
Program

// Implementation of Dijkstra's Algorithm in C

// importing the standard I/O header file


#include <stdio.h>

// defining some constants


#define INF 9999
#define MAX 10

// prototyping of the function


void DijkstraAlgorithm(int Graph[MAX][MAX], int size, int start);

// defining the function for Dijkstra's Algorithm


void DijkstraAlgorithm(int Graph[MAX][MAX], int size, int start) {
int cost[MAX][MAX], distance[MAX], previous[MAX];
int visited_nodes[MAX], counter, minimum_distance, next_node, i, j;

// creating cost matrix


for (i = 0; i < size; i++)
for (j = 0; j < size; j++)
if (Graph[i][j] == 0)
cost[i][j] = INF;
else
cost[i][j] = Graph[i][j];

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


distance[i] = cost[start][i];
previous[i] = start;
visited_nodes[i] = 0;
}

distance[start] = 0;
visited_nodes[start] = 1;
counter = 1;

while (counter < size - 1) {


minimum_distance = INF;
for (i = 0; i < size; i++)
if (distance[i] < minimum_distance && !visited_nodes[i]) {
minimum_distance = distance[i];
next_node = i;
}

visited_nodes[next_node] = 1;
for (i = 0; i < size; i++)
if (!visited_nodes[i])
if (minimum_distance + cost[next_node][i] < distance[i]) {
distance[i] = minimum_distance + cost[next_node][i];
previous[i] = next_node;
}
counter++;
}

// printing the distance


for (i = 0; i < size; i++)
if (i != start) {
printf("\nDistance from the Source Node to %d: %d", i, distance[i]);
}
}

// main function
int main() {
// defining variables
int Graph[MAX][MAX], i, j, size, source;
// declaring the size of the matrix
size = 7;

// declaring the nodes of graph


Graph[0][0] = 0;
Graph[0][1] = 4;
Graph[0][2] = 0;
Graph[0][3] = 0;
Graph[0][4] = 0;
Graph[0][5] = 8;
Graph[0][6] = 0;
Graph[1][0] = 4;
Graph[1][1] = 0;
Graph[1][2] = 8;
Graph[1][3] = 0;
Graph[1][4] = 0;
Graph[1][5] = 11;
Graph[1][6] = 0;

Graph[2][0] = 0;
Graph[2][1] = 8;
Graph[2][2] = 0;
Graph[2][3] = 7;
Graph[2][4] = 0;
Graph[2][5] = 4;
Graph[2][6] = 0;

Graph[3][0] = 0;
Graph[3][1] = 0;
Graph[3][2] = 7;
Graph[3][3] = 0;
Graph[3][4] = 9;
Graph[3][5] = 14;
Graph[3][6] = 0;

Graph[4][0] = 0;
Graph[4][1] = 0;
Graph[4][2] = 0;
Graph[4][3] = 9;
Graph[4][4] = 0;
Graph[4][5] = 10;
Graph[4][6] = 2;

Graph[5][0] = 0;
Graph[5][1] = 0;
Graph[5][2] = 4;
Graph[5][3] = 14;
Graph[5][4] = 10;
Graph[5][5] = 0;
Graph[5][6] = 2;
Graph[6][0] = 0;
Graph[6][1] = 0;
Graph[6][2] = 0;
Graph[6][3] = 0;
Graph[6][4] = 2;
Graph[6][5] = 0;
Graph[6][6] = 1;

source = 0;
// calling the DijkstraAlgorithm() function by passing the Graph, the number of nodes and
the source node
DijkstraAlgorithm(Graph, size, source);

return 0;
}

Output

Distance from the Source Node to 1: 4


Distance from the Source Node to 2: 12
Distance from the Source Node to 3: 19
Distance from the Source Node to 4: 12
Distance from the Source Node to 5: 8
Distance from the Source Node to 6: 10

Conclusion: Thus we have studied about Dijkstra Algorithm.


Experiment No 4

Aim: Write a program to find all pair shortest path-Floyd Warshall.

Theory:

The Floyd Warshall Algorithm is an all pair shortest path algorithm


unlike Dijkstra and Bellman Ford which are single source shortest path algorithms. This
algorithm works for both the directed and undirected weighted graphs. But, it does not
work for the graphs with negative cycles (where the sum of the edges in a cycle is
negative). It follows Dynamic Programming approach to check every possible path going
via every possible node in order to calculate shortest distance between every pair of nodes.

Algorithm

Floyd-Warshall(w, n){ // w: weights, n: number of vertices


for i = 1 to n do // initialize, D (0) = [wij]
for j = 1 to n
do{ d[i, j] = w[i,
j];
}
for k = 1 to n do // Compute D (k) from D (k-1)
for i = 1 to n do
for j = 1 to n do
if (d[i, k] + d[k, j] < d[i, j]){
d[i, j] = d[i, k] + d[k, j];
}
return d[1..n, 1..n];
}
Program

#include <stdio.h>
void floyds(int b[3][3]) { int i, j, k;
for (k = 0; k < 3; k++) { for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
if ((b[i][k] * b[k][j] != 0) && (i != j)) {
if ((b[i][k] + b[k][j] < b[i][j]) || (b[i][j] == 0)) { b[i][j] = b[i][k] + b[k][j];
}
}
}
}
}
for (i = 0; i < 3; i++) {
printf("Minimum Cost With Respect to Node: %d\n", i); for (j = 0; j < 3; j++) {
printf("%d\t", b[i][j]);
}
}
}

int main() {
int b[3][3] = {0};
b[0][1] = 10;
b[1][2] = 15;
b[2][0] = 12;
floyds(b); return 0;
}

Output

Minimum Cost With Respect to Node: 0


0 10 25 Minimum Cost With Respect to Node: 1
27 0 15 Minimum Cost With Respect to Node: 2
12 22 0

Conclusion: Thus we have studied about Floyd Warshall algorithm


Experiment No 5

Aim:Write a program to implement travelling salesperson problem using Dynamic


programming.

Theory:

Definition
Given a set of cities and the distance between each possible pair, the Travelling
Salesman Problem is to find the best possible way of ‘visiting all the cities exactly
once and returning to the starting point’.
The (original) problem can be formulated as:"If there are n cities a salesman must
visit, and the distance between each pair of these cities is given, find the shortest
tour where each city is visited exactly once and returning to your starting point."

Dynamic Programming
Dynamic programming is typically applied to optimization problems. For each
given problem, we may get any number of solutions we seek for optimum solution
(i.e. minimum value or maximum value solution). And such an optimal solution
becomes the solution to the given problem. It is guaranteed that the dynamic
programming will generate optimal solution using principle of optimality.

Problem Description: Let G be directed graph denoted by (V, E) where V denotes


set of vertices and E denotes set of edges. The edges are given along with their
cost Cij. The cost Cij>0 for all i and j. If there is no edge between i and j then
Cij=∞.

A tour for a graph should be such that all the vertices should be visited only once
andcost of the tour is sum of the cost of edges on the tour. The travelling
salesperson problem is to find the tour of minimum cost.

Dynamic programming is used to solve this problem.


Step 1:Let the function C (1, V-{1}) is the total length of the tour terminatingat
1. The objective of TSP problem is that the cost of this tour should be minimum.
Let d [i, j] be the shortest path between two vertices i and j.
Step 2: Let V1, V2… Vn be the sequence of vertices followed in optimal tour.
Then (V1, V2,… Vn) must be a shortest path from V1 to Vn which passes through
each vertex exactly once.
Here the principle of optimality is used. The path Vi, Vi+1,…Vj must be optimal
for all paths beginning at v(i), ending at v(j),and passing through all the
intermediate vertices{V(i+1)..V(j-1)} once.
Step 3:Following formula can be used to obtain the optimum cost tour.
Cost(i,S) = min{d[i,j] + Cost(j,S-{j})} where jЄS and iЄS
Algorithm

1. Scan the number of vertices to be traversed.


2. Maintain the list of distances from every vertex to every other
possiblevertex.
3. Store the source vertex from the list.
4. If there is no path between two cities then put zero.

5. Go through all the vertices.


6. Recursively record the path of traversal.
7. Calculate the minimum path each time and update it.
8. Select the new path with the minimum cost as your optimal path.
9. Display the path and the cost related to it.
Program

#include <stdio.h>
#include <limits.h>
#define MAX 9999
int n = 4;
int distan[20][20] = {
{0, 22, 26, 30},
{30, 0, 45, 35},
{25, 45, 0, 60},
{30, 35, 40, 0}};
int DP[32][8];
int TSP(int mark, int position) {
int completed_visit = (1 << n) - 1;
if (mark == completed_visit) {
return distan[position][0];
}
if (DP[mark][position] != -1) {
return DP[mark][position];
}
int answer = MAX;
for (int city = 0; city < n; city++) {
if ((mark & (1 << city)) == 0) {
int newAnswer = distan[position][city] + TSP(mark | (1 << city), city);
answer = (answer < newAnswer) ? answer : newAnswer;
}
}
return DP[mark][position] = answer;
}
int main() {
for (int i = 0; i < (1 << n); i++) {
for (int j = 0; j < n; j++) {
DP[i][j] = -1;
}
}
printf("Minimum Distance Travelled -> %d\n", TSP(1, 0));
return 0;
}
Output
Minimum Distance Travelled -> 122

Conclusion: Thus we have studied about travelling salesperson problem using Dynamic
programming.
Experiment No 6

Aim: Write a program to find longest common subsequence using Dynamic programming.

Theory:

The longest common subsequence problem is finding the longest sequence which exists in
both the given strings.

But before we understand the problem, let us understand what the term subsequence is −

Let us consider a sequence S = <s1, s2, s3, s4, …,sn>. And another sequence Z = <z1, z2, z3,
…,zm> over S is called a subsequence of S, if and only if it can be derived from S deletion of
some elements. In simple words, a subsequence consists of consecutive elements that make
up a small part in a sequence.

Common Subsequence

Suppose, X and Y are two sequences over a finite set of elements. We can say that Z is a
common subsequence of X and Y, if Z is a subsequence of both X and Y.

Longest Common Subsequence

If a set of sequences are given, the longest common subsequence problem is to find a
common subsequence of all the sequences that is of maximal length.

Input: S1 = “AGGTAB”, S2 = “GXTXAYB”

Output: 4

Explanation: The longest subsequence which is present in both strings is “GTAB”.

Input: S1 = “BD”, S2 = “ABCD”

Output: 2

Explanation: The longest subsequence which is present in both strings is “BD”.


Program

/ C program to find longest common subsequence using


// recursion

#include <stdio.h>
#include <string.h>

// Function to return the maximum of two integers


int max(int a, int b)
{
// Return a if a is greater than b, otherwise return b
return (a > b) ? a : b;
}

// Function to find the length of the Longest Common


// Subsequence (LCS) using recursion
int lcsRecursive(char* X, char* Y, int m, int n)
{
// Base case: If either string is empty, LCS length is 0
if (m == 0 || n == 0)
return 0;

// If the characters match, include them in LCS and


// recur for the remaining strings
if (X[m - 1] == Y[n - 1])
return 1 + lcsRecursive(X, Y, m - 1, n - 1);

// If the characters do not match, recursively find LCS


// by excluding one character at a time
else
// Return the maximum of LCS by excluding either the
// last character of X or Y
return max(lcsRecursive(X, Y, m, n - 1),
lcsRecursive(X, Y, m - 1, n));
}

int main()
{
// First string
char X[] = "AGGTAB";
// Second string
char Y[] = "GXTXAYB";
// Length of first string
int m = strlen(X);
// Length of second string
int n = strlen(Y);

// Calculate and print the length of Longest Common


// Subsequence (LCS)
printf("Length of LCS is %d\n",
lcsRecursive(X, Y, m, n));

return 0;
}

Output

Length of LCS is 4

Conclusion: Thus we have studied about longest common subsequence.


Experiment No 7

Aim: Write a program to find N-queen problem using Backtracking and Branch and bound.

Theory:

Let’s begin by describing the backtracking solution. “The idea is to place queens one by
one in different columns, starting from the leftmost column. When we place a queen in a
column, we check for clashes with already placed queens. In the current column, if we find
a row for which there is no clash, we mark this row and column as part of the solution. If
we do not find such a row due to clashes, then we backtrack and return false.”

Placing 1st queen on (3, 0) and 2nd queen on (5, 1)


1. For the 1st Queen, there are total 8 possibilities as we can place 1st Queen in any row of
first column. Let’s place Queen 1 on row 3.
2. After placing 1st Queen, there are 7 possibilities left for the 2nd Queen. But wait, we
don’t really have 7 possibilities. We cannot place Queen 2 on rows 2, 3 or 4 as those
cells are under attack from Queen 1. So, Queen 2 has only 8 – 3 = 5 valid positions left.
3. After picking a position for Queen 2, Queen 3 has even fewer options as most of the
cells in its column are under attack from the first 2 Queens.
Basically, we have to ensure 4 things:
1. No two queens share a column.
2. No two queens share a row.
3. No two queens share a top-right to left-bottom diagonal.
4. No two queens share a top-left to bottom-right diagonal.
Program

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

int N;

// Function to print the solution board


void printSolution(int** board)
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
// Print each cell of the board
printf("%d ", board[i][j]);
}
// Move to the next line after printing each row
printf("\n");
}
}

// Function to allocate memory for the 2D board


int** allocateBoard()
{
// Allocate memory for rows
int** board = (int**)malloc(N * sizeof(int*));
for (int i = 0; i < N; i++) {
// Allocate memory for columns in each row
board[i] = (int*)malloc(N * sizeof(int));
}
// Return the allocated board
return board;
}

// Function to allocate memory for a boolean array


bool* allocateBooleanArray(int size)
{
// Allocate memory for the array
bool* array = (bool*)malloc(size * sizeof(bool));
for (int i = 0; i < size; i++) {
// Initialize all elements of the array to false
array[i] = false;
}
// Return the allocated boolean array
return array;
}
// Optimized function to check if placing a queen at
// position (row, col) is safe
bool isSafe(int row, int col, bool* rows,
bool* leftDiagonals, bool* rightDiagonals)
{
if (rows[row] || leftDiagonals[row + col]
|| rightDiagonals[col - row + N - 1]) {

// If any of the row, left diagonal, or right


// diagonal is occupied, return false
return false;
}
// Otherwise, it's safe to place a queen at position
// (row, col)
return true;
}

// Recursive function to solve the N-Queen problem


bool solve(int** board, int col, bool* rows,
bool* leftDiagonals, bool* rightDiagonals)
{
if (col >= N) {
// If all queens are placed successfully, return
// true
return true;
}

// Try placing queen in each row of the current column


for (int i = 0; i < N; i++) {
if (isSafe(i, col, rows, leftDiagonals,
rightDiagonals)) {
// Mark the row and diagonals as occupied
rows[i] = true;
leftDiagonals[i + col] = true;
rightDiagonals[col - i + N - 1] = true;
// Place the queen at position (i, col)
board[i][col] = 1;

// Recur to place queens in subsequent columns


if (solve(board, col + 1, rows, leftDiagonals,
rightDiagonals)) {
// If placing queen in the next column leads
// to a solution, return true
return true;
}
// Backtrack: Unmark the row and diagonals, and
// remove the queen
rows[i] = false;
leftDiagonals[i + col] = false;
rightDiagonals[col - i + N - 1] = false;
board[i][col] = 0; // Remove the queen from
// position (i, col)
}
}
// If no position is safe in the current column, return
// false
return false;
}

int main()
{

// Taking input from the user for the size of the board
printf(
"Enter the number of rows for the square board: ");
scanf("%d", &N);

// Allocate memory for the board, and boolean arrays for


// rows and diagonals
int** board = allocateBoard();
bool* rows = allocateBooleanArray(N);
bool* leftDiagonals = allocateBooleanArray(2 * N - 1);
bool* rightDiagonals = allocateBooleanArray(2 * N - 1);

// Solve the N-Queen problem and print the solution


if (solve(board, 0, rows, leftDiagonals,
rightDiagonals)) {
printf("Solution found:\n");
// Print the board configuration
printSolution(board);
}
else {
printf("Solution does not exist\n");
}
// Free dynamically allocated memory
for (int i = 0; i < N; i++) {
free(board[i]);
}
free(board);
free(rows);
free(leftDiagonals);
free(rightDiagonals);

return 0;
}

Input:
Enter the no of rows for the square Board: 8

Output:

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

Conclusion: Thus we have studied about N-queen problem.


Experiment No 8

Aim: Write a program to find the Naïve string matching algorithms.

Theory:

Naive algorithm for Pattern Searching


Given text string with length n and a pattern with length m, the task is to prints all
occurrences of pattern in text.
Note: You may assume that n > m.
Examples:
Input: text = “THIS IS A TEST TEXT”, pattern = “TEST”
Output: Pattern found at index 10
Input: text = “AABAACAADAABAABA”, pattern = “AABA”
Output: Pattern found at index 0, Pattern found at index 9, Pattern found at index 12
Program

#include <stdio.h>
#include <string.h>

void search(char* pat, char* txt) {


int M = strlen(pat);
int N = strlen(txt);

// A loop to slide pat[] one by one


for (int i = 0; i <= N - M; i++) {
int j;

// For current index i, check for pattern match


for (j = 0; j < M; j++) {
if (txt[i + j] != pat[j]) {
break;
}
}

// If pattern matches at index i


if (j == M) {
printf("Pattern found at index %d\n", i);
}
}
}

int main() {
// Example 1
char txt1[] = "AABAACAADAABAABA";
char pat1[] = "AABA";
printf("Example 1:\n");
search(pat1, txt1);

// Example 2
char txt2[] = "agd";
char pat2[] = "g";
printf("\nExample 2:\n");
search(pat2, txt2);

return 0;
}
Output:

Pattern found at index 0


Pattern found at index 9
Pattern found at index 13

Conclusion: Thus we have studied about Naïve string matching algorithms.


Experiment No 9

Aim: Write a program to find the Knuth Morris Pratt algorithm.

Theory:

Knuth Morris Pratt algorithm

Given a text txt[0..n-1] and a pattern pat[0..m-1], write a function search(char pat[], char
txt[]) that prints all occurrences of pat[] in txt[]. You may assume that n > m.
Examples:
Input: txt[] = "THIS IS A TEST TEXT"
pat[] = "TEST"
Output: Pattern found at index 10

Input: txt[] = "AABAACAADAABAABA"


pat[] = "AABA"
Output: Pattern found at index 0
Pattern found at index 9
Pattern found at index 12
Program

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

// Fills lps[] for given pattern pat


void computeLPSArray(const char* pat, int M, int* lps){
// Length of the previous longest prefix suffix
int len = 0;

// lps[0] is always 0
lps[0] = 0;

// Loop calculates lps[i] for i = 1 to M-1


int i = 1;
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
}
else {
if (len != 0) {
len = lps[len - 1];
}
else {
lps[i] = 0;
i++;
}
}
}
}

// Prints occurrences of pat in txt and returns an array of


// occurrences
int* KMPSearch(const char* pat, const char* txt, int* count){
int M = strlen(pat);
int N = strlen(txt);
// Create lps[] that will hold the longest prefix suffix
// values for pattern
int* lps = (int*)malloc(M * sizeof(int));

// Preprocess the pattern (calculate lps[] array)


computeLPSArray(pat, M, lps);

int* result = (int*)malloc(N * sizeof(int));

// Number of occurrences found


*count = 0;

int i = 0; // index for txt


int j = 0; // index for pat

while ((N - i) >= (M - j)) {


if (pat[j] == txt[i]) {
j++;
i++;
}

if (j == M) {

// Record the occurrence (1-based index)


result[*count] = i - j + 1;
(*count)++;
j = lps[j - 1];
}
else if (i < N && pat[j] != txt[i]) {
if (j != 0) {
j = lps[j - 1];
}
else {
i = i + 1;
}
}
}
free(lps);
return result;
}
int main(){
const char txt[] = "geeksforgeeks";
const char pat[] = "geeks";
int count;

// Call KMPSearch and get the array of occurrences


int* result = KMPSearch(pat, txt, &count);

// Print all the occurrences (1-based indices)


for (int i = 0; i < count; i++) {
printf("Pattern found at index: %d ", result[i]);
printf("\n");

}
printf("\n");

// Free the allocated memory


free(result);

return 0;
}

Output:

Pattern found at index: 1


Pattern found at index: 9

Conclusion: Thus we have studied about Knuth Morris Pratt algorithm.


Experiment No 10

Aim: Write a program to find the Rabin Karp algorithm.

Theory:

Rabin Karp algorithm

Given a text txt[0..n-1] and a pattern pat[0..m-1], write a function search(char pat[], char
txt[]) that prints all occurrences of pat[] in txt[]. You may assume that n > m.
Examples:
Input: txt[] = "THIS IS A TEST TEXT"
pat[] = "TEST"
Output: Pattern found at index 10

Input: txt[] = "AABAACAADAABAABA"


pat[] = "AABA"
Output: Pattern found at index 0
Pattern found at index 9
Pattern found at index 12

Rabin-Karp algorithm also slides the pattern one by one. But unlike the Naive algorithm,
Rabin Karp algorithm matches the hash value of the pattern with the hash value of current
substring of text, and if the hash values match then only it starts matching individual
characters. So Rabin Karp algorithm needs to calculate hash values for following strings.
1) Pattern itself.
2) All the substrings of text of length m.
Program

/* Following program is a C implementation of Rabin Karp


Algorithm given in the CLRS book */
#include <stdio.h>
#include <string.h>

// d is the number of characters in the input alphabet


#define d 256

/* pat -> pattern


txt -> text
q -> A prime number
*/
void search(char pat[], char txt[], int q)
{
int M = strlen(pat);
int N = strlen(txt);
int i, j;
int p = 0; // hash value for pattern
int t = 0; // hash value for txt
int h = 1;

// The value of h would be "pow(d, M-1)%q"


for (i = 0; i < M - 1; i++)
h = (h * d) % q;

// Calculate the hash value of pattern and first


// window of text
for (i = 0; i < M; i++) {
p = (d * p + pat[i]) % q;
t = (d * t + txt[i]) % q;
}

// Slide the pattern over text one by one


for (i = 0; i <= N - M; i++) {

// Check the hash values of current window of text


// and pattern. If the hash values match then only
// check for characters one by one
if (p == t) {
/* Check for characters one by one */
for (j = 0; j < M; j++) {
if (txt[i + j] != pat[j])
break;
}

// if p == t and pat[0...M-1] = txt[i, i+1,


// ...i+M-1]
if (j == M)
printf("Pattern found at index %d \n", i);
}

// Calculate hash value for next window of text:


// Remove leading digit, add trailing digit
if (i < N - M) {
t = (d * (t - txt[i] * h) + txt[i + M]) % q;

// We might get negative value of t, converting


// it to positive
if (t < 0)
t = (t + q);
}
}
}

/* Driver Code */
int main()
{
char txt[] = "GEEKS FOR GEEKS";
char pat[] = "GEEK";

// A prime number
int q = 101;

// function call
search(pat, txt, q);
return 0;
}

Output:
Pattern found at index 0
Pattern found at index 10

Conclusion: Thus we have studied about Rabin Karp algorithm.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy