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: 𝑂(𝑁!)