0% found this document useful (0 votes)
12 views

DAA Lab File

The document outlines various algorithms including Linear Search, Binary Search, Merge Sort, Quick Sort, Selection Sort, Bubble Sort, Insertion Sort, and Strassen's Matrix Multiplication. Each algorithm is implemented in C++ with accompanying time complexity analysis for best, worst, and average cases. The document serves as a comprehensive guide for understanding and analyzing these fundamental algorithms.
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)
12 views

DAA Lab File

The document outlines various algorithms including Linear Search, Binary Search, Merge Sort, Quick Sort, Selection Sort, Bubble Sort, Insertion Sort, and Strassen's Matrix Multiplication. Each algorithm is implemented in C++ with accompanying time complexity analysis for best, worst, and average cases. The document serves as a comprehensive guide for understanding and analyzing these fundamental algorithms.
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/ 56

PROGRAM-1

Aim: To implement Linear search and Binary search and analyse its time
complexity.

Code:
#include <iostream>
using namespace std;

// linear search
int linearSearch(int arr[], int n, int target) {
for (int i = 0; i < n; ++i) {
if (arr[i] == target) {
return i; // Target found at index i
}
}
return -1; // Target not found
}

//binary search
int binarySearch(int arr[], int n, int target) {
int left = 0, right = n - 1;
while (left <= right) {
int mid = left + (right - left) / 2;

if (arr[mid] == target) {
return mid; // Target found at index mid
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1; // Target not found
}

int main() {

// linear search
int arr1[] = {70, 20, 60, 90, 50};
int n1 = sizeof(arr1) / sizeof(arr1[0]);
int target;

cout << "Enter the element to search for using linear search: ";
cin >> target;

int result1 = linearSearch(arr1, n1, target);


if (result1 != -1) {
cout << "Element found at index: " << result1 << endl;
}else {
cout << "Element not found" << endl;
}
// binary search
int arr2[] = {10, 20, 30, 40, 50};
int n2 = sizeof(arr2) / sizeof(arr2[0]);

cout << "Enter the element to search for using binary search: ";
cin >> target;

int result2 = linearSearch(arr2, n2, target);


if (result2 != -1) {
cout << "Element found at index: " << result2 << endl;
}else {
cout << "Element not found" << endl;
}

return 0;
}

Output:
Linear Search Time Complexity:
 Best case: Ω(1)
 Worst case: O(n)
 Average case: θ(n)

Binary Search Time Complexity:


 Best case: Ω(1)
 Worst case: O(logn)
 Average case: θ(logn)
PROGRAM-2

Aim: To implement following algorithm using array as a data structure and analyse
its time complexity:

2.1: Merge Sort


Code:
#include <iostream>

// Function to merge two halves


void merge(int arr[], int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;

// Create temporary arrays


int* leftArr = new int[n1];
int* rightArr = new int[n2];

// Copy data to temporary arrays leftArr[] and rightArr[]


for (int i = 0; i < n1; i++)
leftArr[i] = arr[left + i];
for (int j = 0; j < n2; j++)
rightArr[j] = arr[mid + 1 + j];

// Merge the temporary arrays back into arr[left..right]


int 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++;
}

// Copy the remaining elements of leftArr[], if any


while (i < n1) {
arr[k] = leftArr[i];
i++;
k++;
}

// Copy the remaining elements of rightArr[], if any


while (j < n2) {
arr[k] = rightArr[j];
j++;
k++;
}

// Free the allocated memory


delete[] leftArr;
delete[] rightArr;
}

// Function to implement merge sort


void mergeSort(int arr[], int left, int right) {
if (left < right) {
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);
}
}

// Utility function to print the array


void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
std::cout << arr[i] << " ";
std::cout << std::endl;
}

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

std::cout << "Given array is \n";


printArray(arr, arr_size);

mergeSort(arr, 0, arr_size - 1);

std::cout << "Sorted array is \n";


printArray(arr, arr_size);
return 0;
}

Output:

Time Complexity:
 Best case: Ω(n logn)
 Worst case: O(n logn)
 Average case: θ(n logn)
2.2: Quick Sort
Code:
#include <iostream>

// Function to swap two elements


void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}

// Function to partition the array


int partition(int arr[], int low, int high)
{
int pivot = arr[high]; // Pivot element
int i = (low - 1); // Index of smaller element

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


{
// If current element is smaller than or equal to pivot
if (arr[j] <= pivot)
{
i++; // Increment index of smaller element
swap(arr[i], arr[j]);
}
}
swap(arr[i + 1], arr[high]);
return (i + 1);
}

// Function to implement Quick Sort


void quickSort(int arr[], int low, int high)
{
if (low < high)
{
// Partitioning index
int pi = partition(arr, low, high);

// Separately sort elements before and after partition


quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}

// Utility function to print the array


void printArray(int arr[], int size)
{
for (int i = 0; i < size; i++)
std::cout << arr[i] << " ";
std::cout << std::endl;
}
int main()
{
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr) / sizeof(arr[0]);

std::cout << "Given array is \n";


printArray(arr, n);

quickSort(arr, 0, n - 1);

std::cout << "Sorted array: \n";


printArray(arr, n);
return 0;
}

Output:

Time Complexity:
 Best case: Ω(n logn)
 Worst case: O(n )
 Average case: θ(n logn)
PROGRAM-3

Aim: To implement following algorithm using array as a data structure and analyse
its time complexity:

3.1: Selection Sort


Code:
#include <iostream>
using namespace std;

// Function to perform selection sort


void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
// Find the minimum element in the unsorted portion of the array
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}

// Swap the found minimum element with the first element of the unsorted
portion
if (minIndex != i) {
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}

// Function to print an array


void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}

int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);

cout << "Original array: ";


printArray(arr, n);

selectionSort(arr, n);

cout << "Sorted array: ";


printArray(arr, n);

return 0;
}
Output:

Time Complexity:
 Best case: Ω(n )
 Worst case: O(n )
 Average case: θ(n )
3.2: Bubble Sort
Code:
#include <iostream>
using namespace std;

void bubbleSort(int arr[], int n) {


bool swapped;
for (int i = 0; i < n - 1; ++i) {
swapped = false;
for (int j = 0; j < n - i - 1; ++j) {
if (arr[j] > arr[j + 1]) {
// Swap if they are in the wrong order
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
// If no elements were swapped, the array is already sorted
if (!swapped) break;
}
}

void printArray(int arr[], int size) {


for (int i = 0; i < size; ++i) {
cout << arr[i] << " ";
}
cout << endl;
}

int main() {
int arr[] = {64, 34, 25, 12, 22, 11, 90};
int n = sizeof(arr) / sizeof(arr[0]);

cout << "Original array: ";


printArray(arr, n);

bubbleSort(arr, n);

cout << "Sorted array: ";


printArray(arr, n);
return 0;
}

Output:

Time Complexity:
 Best case: Ω(n)
 Worst case: O(n )
 Average case: θ(n )
3.3: Insertion Sort
Code:
#include <iostream>
using namespace std;

// Function to perform insertion sort


void insertionSort(int arr[], int n) {
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 ahead of their current position
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
}

void printArray(int arr[], int size) {


for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}

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

cout << "Original array: ";


printArray(arr, n);

insertionSort(arr, n);

cout << "Sorted array: ";


printArray(arr, n);

return 0;
}

Output:

Time Complexity:
 Best case: Ω(n)
 Worst case: O(n )
 Average case: θ(n )
PROGRAM-4

Aim: To implement matrix multiplication using Stassen’s algorithm.


Code:
#include <iostream>
#include <cmath>
using namespace std;

const int MAX = 128; // Define maximum matrix size

// Function to add two matrices


void add(int A[MAX][MAX], int B[MAX][MAX], int C[MAX][MAX], int size)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
C[i][j] = A[i][j] + B[i][j];
}
}
}

// Function to subtract two matrices


void subtract(int A[MAX][MAX], int B[MAX][MAX], int C[MAX][MAX], int size)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
C[i][j] = A[i][j] - B[i][j];
}
}
}

// Strassen’s matrix multiplication function


void strassen(int A[MAX][MAX], int B[MAX][MAX], int C[MAX][MAX], int size)
{
if (size == 1)
{
C[0][0] = A[0][0] * B[0][0];
return;
}

int newSize = size / 2;


int A11[MAX][MAX], A12[MAX][MAX], A21[MAX][MAX], A22[MAX][MAX];
int B11[MAX][MAX], B12[MAX][MAX], B21[MAX][MAX], B22[MAX][MAX];
int C11[MAX][MAX], C12[MAX][MAX], C21[MAX][MAX], C22[MAX][MAX];
int M1[MAX][MAX], M2[MAX][MAX], M3[MAX][MAX], M4[MAX][MAX];
int M5[MAX][MAX], M6[MAX][MAX], M7[MAX][MAX];
int temp1[MAX][MAX], temp2[MAX][MAX];

// Dividing the matrices into submatrices


for (int i = 0; i < newSize; i++)
{
for (int j = 0; j < newSize; j++)
{
A11[i][j] = A[i][j];
A12[i][j] = A[i][j + newSize];
A21[i][j] = A[i + newSize][j];
A22[i][j] = A[i + newSize][j + newSize];

B11[i][j] = B[i][j];
B12[i][j] = B[i][j + newSize];
B21[i][j] = B[i + newSize][j];
B22[i][j] = B[i + newSize][j + newSize];
}
}

// M1 = (A11 + A22) * (B11 + B22)


add(A11, A22, temp1, newSize);
add(B11, B22, temp2, newSize);
strassen(temp1, temp2, M1, newSize);

// M2 = (A21 + A22) * B11


add(A21, A22, temp1, newSize);
strassen(temp1, B11, M2, newSize);

// M3 = A11 * (B12 - B22)


subtract(B12, B22, temp1, newSize);
strassen(A11, temp1, M3, newSize);

// M4 = A22 * (B21 - B11)


subtract(B21, B11, temp1, newSize);
strassen(A22, temp1, M4, newSize);

// M5 = (A11 + A12) * B22


add(A11, A12, temp1, newSize);
strassen(temp1, B22, M5, newSize);

// M6 = (A21 - A11) * (B11 + B12)


subtract(A21, A11, temp1, newSize);
add(B11, B12, temp2, newSize);
strassen(temp1, temp2, M6, newSize);

// M7 = (A12 - A22) * (B21 + B22)


subtract(A12, A22, temp1, newSize);
add(B21, B22, temp2, newSize);
strassen(temp1, temp2, M7, newSize);

// Calculating C11, C12, C21, C22


add(M1, M4, temp1, newSize);
subtract(temp1, M5, temp2, newSize);
add(temp2, M7, C11, newSize);
add(M3, M5, C12, newSize);

add(M2, M4, C21, newSize);

add(M1, M3, temp1, newSize);


subtract(temp1, M2, temp2, newSize);
add(temp2, M6, C22, newSize);

// Combining the results into a single matrix


for (int i = 0; i < newSize; i++)
{
for (int j = 0; j < newSize; j++)
{
C[i][j] = C11[i][j];
C[i][j + newSize] = C12[i][j];
C[i + newSize][j] = C21[i][j];
C[i + newSize][j + newSize] = C22[i][j];
}
}
}

// Helper function to display a matrix


void displayMatrix(int matrix[MAX][MAX], int size)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
cout << matrix[i][j] << " ";
}
cout << endl;
}
cout.flush(); // Flush the output to the terminal
}

int main()
{
int n;
cout << "Enter the size of the matrices (must be a power of 2): ";
cin >> n;

int A[MAX][MAX], B[MAX][MAX], C[MAX][MAX];

cout << "Enter elements of matrix A:" << endl;


for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> A[i][j];
}
}
cout << "Enter elements of matrix B:" << endl;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> B[i][j];
}
}

// Initialize the result matrix C with zeros


for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
C[i][j] = 0;
}
}

// Perform Strassen's multiplication


strassen(A, B, C, n);

cout << "Resultant matrix after multiplication using Strassen's algorithm:" <<
endl;
displayMatrix(C, n); // <--- Call displayMatrix to show the result

return 0;
}
Output:

Time Complexity:
 Standard matrix multiplication: 𝑂(n )
 Strassen’s algorithm: 𝑂(n . )
PROGRAM-5

Aim: To implement Hu man Coding and analyse its time complexity.


Code:
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>

using namespace std;

//Node Structure for Hu man Tree


struct Node
{
char ch;
int freq;
Node *left, *right;

Node(char ch, int freq)


{
this->ch = ch;
this->freq = freq;
left = right = nullptr;
}

Node(int freq, Node *left, Node *right)


{
this->ch = '\0';
this->freq = freq;
this->left = left;
this->right = right;
}
};

//Comparator for priority queue to order nodes by frequency


struct Compare
{
bool operator()(Node *left, Node *right)
{
return left->freq > right->freq;
}
};

//Function to traverse the Hu man Tree and store the Hu man Codes in a map
void encode(Node *root, string str, unordered_map<char, string> &hu manCode)
{
if (!root)
{
return;
}

if (!root->left && !root->right)


{
hu manCode[root->ch] = str;
}

encode(root->left, str + "0", hu manCode);


encode(root->right, str + "1", hu manCode);
}

//Function to calculate the total number of bits used based on the Hu man
Codes
int calculateTotalBits(const unordered_map<char, string> &hu manCode, const
unordered_map<char, int> &freq)
{
int totalBits = 0;
for (auto &pair : freq)
{
char ch = pair.first;
int frequency = pair.second;
int codeLength = hu manCode.at(ch).length();
totalBits += frequency * codeLength;
}
return totalBits;
}

//Function to build Hu man Tree and calculate the total bits used
void buildHu manTree(const vector<pair<char, int>> &charFreq)
{
priority_queue<Node *, vector<Node *>, Compare> pq;

for (auto &pair : charFreq)


{
pq.push(new Node(pair.first, pair.second));
}
while (pq.size() != 1)
{
Node *left = pq.top();
pq.pop();
Node *right = pq.top();
pq.pop();

Node *newNode = new Node(left->freq + right->freq, left, right);


pq.push(newNode);
}
Node *root = pq.top();

unordered_map<char, string> hu manCode;


encode(root, "", hu manCode);

cout << "Character\tFrequency\tHu man code\tBits Used\n";


cout << "-----------------------------------------------------\n";
int totalBits = 0;
for (auto &pair : charFreq)
{
char ch = pair.first;
int frequency = pair.second;
string code = hu manCode[ch];
int bitsUsed = frequency * code.length();
cout << ch << "\t\t" << frequency << "\t\t" << code << "\t\t" << bitsUsed <<
"\n";
totalBits += bitsUsed;
}
cout << "-----------------------------------------------------\n";
cout << "Total bits used: " << totalBits << endl;
}

int main()
{
vector<pair<char, int>> charFreq = {{'a', 42},
{'b', 20},
{'c', 5},
{'d', 10},
{'e', 11},
{'f', 12}};
buildHu manTree(charFreq);
return 0;
}
Output:

Time Complexity:
 Building Hu man Tree: O(nlogn)
 Encoding: O(n)
 Decoding: O(n)
PROGRAM-6

Aim: To implement Minimum Spanning Tree and analyse its time complexity.

6.1: Prim’s Algorithm


Code:
#include <iostream>
#include <vector>
#include <climits> // For INT_MAX
using namespace std;

// Function to find the minimum vertex (node) that has not been included in
MST
int minKey(vector<int> &key, vector<bool> &mstSet, int V)
{
int min = INT_MAX, minIndex;

for (int v = 1; v <= V; v++)


{
if (!mstSet[v] && key[v] < min)
{
min = key[v];
minIndex = v;
}
}
return minIndex;
}

// Prim's algorithm to find MST


void primMST(vector<vector<int>> &graph, int V)
{
vector<int> parent(V + 1); // Array to store the MST
vector<int> key(V + 1, INT_MAX); // Key values used to pick the minimum
weight edge
vector<bool> mstSet(V + 1, false); // To represent vertices included in MST
int minCost = 0; // Variable to store the minimum cost of MST

// Start with the first vertex


key[1] = 0; // Starting node is always included in MST
parent[1] = -1; // First node is always the root of MST

for (int count = 1; count < V; count++)


{
int u = minKey(key, mstSet, V); // Pick the minimum key vertex
mstSet[u] = true; // Mark the vertex as included in MST

// Update key values and parent index of the adjacent vertices


for (int v = 1; v <= V; v++)
{
if (graph[u][v] && !mstSet[v] && graph[u][v] < key[v])
{
parent[v] = u;
key[v] = graph[u][v];
}
}
}

// Print the MST and calculate the minimum cost


cout << "Edge Weight\n";
for (int i = 2; i <= V; i++)
{
cout << parent[i] << " - " << i << " " << graph[i][parent[i]] << endl;
minCost += graph[i][parent[i]]; // Add the weight to the total cost
}

// Print the minimum cost of the MST


cout << "Minimum cost of the MST: " << minCost << endl;
}

int main()
{
int V; // Number of vertices
cout << "Enter the number of vertices: ";
cin >> V;

// Create an adjacency matrix (V+1 to index from 1)


vector<vector<int>> graph(V + 1, vector<int>(V + 1, 0));

int E; // Number of edges


cout << "Enter the number of edges: ";
cin >> E;

cout << "Enter the edges and their weights (u v w): \n";
for (int i = 0; i < E; i++)
{
int u, v, w;
cin >> u >> v >> w; // Enter the edge (u-v) and its weight w
graph[u][v] = w;
graph[v][u] = w; // Since it's an undirected graph
}

// Perform Prim's algorithm to find the MST


primMST(graph, V);

return 0;
}
Output:

Time Complexity:
 Best case: 𝑂(V )
 Worst case: 𝑂(V )
 Average case: 𝑂(V )
6.2: Kruskal’s Algorithm
Code:
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// Structure to represent an edge in the graph


struct Edge
{
int u, v, weight;
};

// Structure to represent a graph


class Graph
{
public:
int V, E; // Number of vertices and edges
vector<Edge> edges;

Graph(int V, int E)
{
this->V = V;
this->E = E;
}
// Function to add an edge to the graph
void addEdge(int u, int v, int weight)
{
edges.push_back({u, v, weight});
}

// Utility function to find the subset of an element u


int findParent(int u, vector<int> &parent)
{
if (u == parent[u])
return u;
return parent[u] = findParent(parent[u], parent);
}

// Union of two sets u and v


void unionSets(int u, int v, vector<int> &parent, vector<int> &rank)
{
u = findParent(u, parent);
v = findParent(v, parent);

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


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

// Function to implement Kruskal's algorithm to find the MST


void kruskalMST()
{
vector<Edge> result;
int mst_cost = 0;

// Step 1: Sort all edges based on their weights


sort(edges.begin(), edges.end(), [](Edge a, Edge b)
{ return a.weight < b.weight; });

// Initialize parent and rank for each vertex


vector<int> parent(V + 1), rank(V + 1, 0);

// Initially, each vertex is its own parent


for (int i = 1; i <= V; ++i)
{
parent[i] = i;
}

// Process each edge in sorted order


for (Edge &edge : edges)
{
int u = edge.u;
int v = edge.v;

// Find parents of u and v


int set_u = findParent(u, parent);
int set_v = findParent(v, parent);

// If they belong to di erent sets, add the edge to the result


if (set_u != set_v)
{
result.push_back(edge);
mst_cost += edge.weight;
unionSets(set_u, set_v, parent, rank);
}
}

// Output the MST edges and the total minimum cost


cout << "Edges in the Minimum Spanning Tree (MST):\n";
for (Edge &edge : result)
{
cout << edge.u << " -- " << edge.v << " == " << edge.weight << endl;
}
cout << "Minimum cost of the MST: " << mst_cost << endl;
}
};

int main()
{
int V, E;

// Input number of vertices and edges


cout << "Enter number of vertices: ";
cin >> V;
cout << "Enter number of edges: ";
cin >> E;

Graph g(V, E);

// Input edges and weights


for (int i = 0; i < E; ++i)
{
int u, v, weight;
cout << "Enter edge (u v weight): ";
cin >> u >> v >> weight;
g.addEdge(u, v, weight);
}
// Apply Kruskal's algorithm to find MST
g.kruskalMST();

return 0;
}

Output:

Time Complexity:
 Best case: (𝐸 𝑙𝑜𝑔𝐸)
 Worst case: (𝐸 𝑙𝑜𝑔𝐸)
 Average case: (𝐸 𝑙𝑜𝑔𝐸)
PROGRAM-7

Aim: To implement Dijkstra‘s algorithm and analyse its time complexity.


Code:
#include <iostream>
#include <vector>
#include <queue>
#include <climits>

using namespace std;

typedef pair<int, int> pii; // Alias for a pair of integers (node, weight)

vector<int> dijkstra(int n, int source, vector<vector<pii>> &graph)


{
vector<int> distance(n + 1, INT_MAX); // Distance array initialized to
"infinity"
priority_queue<pii, vector<pii>, greater<pii>> pq; // Min-heap (priority queue)

// Initialize the source node


distance[source] = 0;
pq.push({0, source}); // Push the source with distance 0

while (!pq.empty())
{
int dist = pq.top().first; // Distance to the node
int node = pq.top().second; // Node number
pq.pop();

// If the distance is outdated, skip this node


if (dist > distance[node])
continue;

// Traverse all adjacent nodes


for (auto &edge : graph[node])
{
int nextNode = edge.first;
int weight = edge.second;

// Relaxation step
if (distance[node] + weight < distance[nextNode])
{
distance[nextNode] = distance[node] + weight;
pq.push({distance[nextNode], nextNode});
}
}
}

return distance;
}

int main()
{
int n, m;
cout << "Enter the number of vertices: ";
cin >> n;
cout << "Enter the number of edges: ";
cin >> m;

vector<vector<pii>> graph(n + 1); // Graph with nodes from 1 to n

cout << "Enter each edge in the format: start end weight\n";
for (int i = 0; i < m; ++i)
{
int u, v, weight;
cin >> u >> v >> weight;
graph[u].push_back({v, weight});
graph[v].push_back({u, weight}); // Remove this line for a directed graph
}

int source;
cout << "Enter the source vertex: ";
cin >> source;

vector<int> distances = dijkstra(n, source, graph);

cout << "Distances from source node " << source << ":\n";
for (int i = 1; i <= n; ++i)
{
if (distances[i] == INT_MAX)
{
cout << "Node " << i << ": Unreachable\n";
}
else
{
cout << "Node " << i << ": " << distances[i] << "\n";
}
}

return 0;
}

Output:

Time Complexity:
 Best case: 𝑂(𝑉 + 𝐸)𝑙𝑜𝑔𝑉
 Worst case: 𝑂(𝑉 + 𝐸)𝑙𝑜𝑔𝑉
 Average case: 𝑂(𝑉 )
PROGRAM-8

Aim: To implement Bellman Ford algorithm and analyse its time complexity.
Code:
#include <iostream>
#include <vector>
#include <climits>
using namespace std;

// Function to implement Bellman-Ford algorithm


bool bellmanFord(int n, int source, vector<vector<int>> &edges, vector<int>
&distances)
{
distances[source] = 0;

// Relax all edges (n - 1) times


for (int i = 1; i < n; ++i)
{
for (const auto &edge : edges)
{
int u = edge[0];
int v = edge[1];
int weight = edge[2];

if (distances[u] != INT_MAX && distances[u] + weight < distances[v])


{
distances[v] = distances[u] + weight;
}
}
}
// Check for negative weight cycles
for (const auto &edge : edges)
{
int u = edge[0];
int v = edge[1];
int weight = edge[2];

if (distances[u] != INT_MAX && distances[u] + weight < distances[v])


{
// Negative cycle detected
return false;
}
}
return true; // No negative weight cycles found
}

int main()
{
int n, m;
cout << "Enter the number of vertices: ";
cin >> n;
cout << "Enter the number of directed edges: ";
cin >> m;

vector<vector<int>> edges;
cout << "Enter each directed edge in the format: start end weight\n";
cout << "(Direction is from 'start' vertex to 'end' vertex)\n";
for (int i = 0; i < m; ++i)
{
int u, v, weight;
cin >> u >> v >> weight;
edges.push_back({u, v, weight});
}

int source;
cout << "Enter the source vertex: ";
cin >> source;

// Initialize distance vector with "infinity"


vector<int> distances(n + 1, INT_MAX);

if (bellmanFord(n, source, edges, distances))


{
cout << "Distances from source vertex " << source << ":\n";
for (int i = 1; i <= n; ++i)
{
if (distances[i] == INT_MAX)
{
cout << "Node " << i << ": Unreachable\n";
}
else
{
cout << "Node " << i << ": " << distances[i] << "\n";
}
}
}
else
{
cout << "Graph contains a negative weight cycle.\n";
}
return 0;
}

Output:

Time Complexity:
 Best case: 𝑂(𝑉. 𝐸)
 Worst case: 𝑂(𝑉. 𝐸)
 Average case: 𝑂(𝑉. 𝐸)
PROGRAM-9

Aim: Implement N Queen's problem using Back Tracking.


Code:
#include <iostream>
#include <vector>

using namespace std;

class NQueens
{
private:
int N; // Size of the chessboard
vector<vector<string>> solutions; // To store the solutions

// Utility function to check if a queen can be placed at board[row][col]


bool isSafe(vector<vector<int>> &board, int row, int col)
{
// Check this column on upper side
for (int i = 0; i < row; i++)
{
if (board[i][col])
return false;
}

// Check upper diagonal on left side


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

// Check upper diagonal on right side


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

return true;
}

// Utility function to solve the N-Queens problem using backtracking


void solveNQueensUtil(vector<vector<int>> &board, int row)
{
if (row == N)
{
// All queens are placed successfully, add to solutions
vector<string> solution;
for (const auto &b : board)
{
string rowStr;
for (int cell : b)
{
rowStr += (cell == 1) ? "Q " : ". ";
}
solution.push_back(rowStr);
}
solutions.push_back(solution);
return;
}

for (int col = 0; col < N; col++)


{
if (isSafe(board, row, col))
{
board[row][col] = 1; // Place the queen

// Recur to place the rest of the queens


solveNQueensUtil(board, row + 1);

// Backtrack: Remove the queen


board[row][col] = 0;
}
}
}
public:
NQueens(int n) : N(n) {}

void solve()
{
vector<vector<int>> board(N, vector<int>(N, 0)); // Initialize the chessboard
solveNQueensUtil(board, 0); // Start from the first row
}

void printSolutions()
{
if (solutions.empty())
{
cout << "No solutions exist for " << N << " queens.\n";
}
else
{
for (const auto &solution : solutions)
{
for (const auto &row : solution)
{
cout << row << endl;
}
cout << endl;
}
}
}
};

int main()
{
int N;
cout << "Enter the number of queens (N): ";
cin >> N;

NQueens nQueens(N);
nQueens.solve();
nQueens.printSolutions();

return 0;
}

Output:

Time Complexity:
 Best case: 𝑂(𝑁!)
 Worst case: 𝑂(𝑁!)
 Average case: 𝑂(𝑁!)

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