0% found this document useful (0 votes)
4 views26 pages

Advanced Algorithms - Lab Manual

The document is a lab manual for Advanced Algorithms at Chaitanya Deemed to be University, detailing implementations of various algorithms in C++. It covers sorting algorithms (Heap Sort, Quick Sort), graph algorithms (Topological Sort, BFS, DFS, Strongly Connected Components), Minimum Spanning Trees (Prim's and Kruskal's algorithms), and advanced techniques like Kadane’s algorithm for the Maximum Subarray Problem and Strassen’s Matrix Multiplication. Each section includes code examples and explanations for the algorithms.

Uploaded by

21jr1a4343
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)
4 views26 pages

Advanced Algorithms - Lab Manual

The document is a lab manual for Advanced Algorithms at Chaitanya Deemed to be University, detailing implementations of various algorithms in C++. It covers sorting algorithms (Heap Sort, Quick Sort), graph algorithms (Topological Sort, BFS, DFS, Strongly Connected Components), Minimum Spanning Trees (Prim's and Kruskal's algorithms), and advanced techniques like Kadane’s algorithm for the Maximum Subarray Problem and Strassen’s Matrix Multiplication. Each section includes code examples and explanations for the algorithms.

Uploaded by

21jr1a4343
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

COMPUTER SCIENCE & ENGINEERING

Advanced Algorithms
LAB MANUAL

CHAITANYA DEEMED TO BE UNIVERSITY


HIMAYATNAGAR MOINABAD,
RANGA REDDY, TELANGANA-500075
1. Implementation of Sorting- heap sort, quick sort, topological sort using queue in
c++
Heap sort
#include <iostream>
using namespace std;

void heapify(int arr[], int n, int i) {


int largest = i;
int left = 2*i + 1;
int right = 2*i + 2;

if (left < n && arr[left] > arr[largest])


largest = left;

if (right < n && arr[right] > arr[largest])


largest = right;

if (largest != i) {
swap(arr[i], arr[largest]);
heapify(arr, n, largest);
}
}

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


for (int i = n/2 - 1; i >= 0; i--)
heapify(arr, n, i);

for (int i = n-1; i > 0; i--) {


swap(arr[0], arr[i]);
heapify(arr, i, 0);
}
}

int main() {
int n;
cout << "Enter number of elements: ";
cin >> n;

int arr[n];
cout << "Enter elements:\n";
for (int i = 0; i < n; i++)

2
cin >> arr[i];

heapSort(arr, n);
cout << "Sorted array:\n";
for (int i = 0; i < n; i++)
cout << arr[i] << " ";

return 0;
}

Quick Sort
#include <iostream>
using namespace std;

int partition(int arr[], int low, int high) {


int pivot = arr[high];
int i = low - 1;

for (int j = low; j < high; j++) {


if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]);
}
}
swap(arr[i+1], arr[high]);
return i + 1;
}

void quickSort(int arr[], int low, int high) {


if (low < high) {
int pi = partition(arr, low, high);

quickSort(arr, low, pi - 1);


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

int main() {
int n;
cout << "Enter number of elements: ";
cin >> n;

3
int arr[n];
cout << "Enter elements:\n";
for (int i = 0; i < n; i++)
cin >> arr[i];

quickSort(arr, 0, n - 1);

cout << "Sorted array:\n";


for (int i = 0; i < n; i++)
cout << arr[i] << " ";

return 0;
}

Topological Sort using Queue (Kahn’s Algorithm)


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

void topologicalSort(int V, vector<vector<int>>& adj) {


vector<int> indegree(V, 0);

// Calculate indegree
for (int i = 0; i < V; i++) {
for (int v : adj[i]) {
indegree[v]++;
}
}

queue<int> q;

// Push nodes with 0 indegree


for (int i = 0; i < V; i++) {
if (indegree[i] == 0)
[Link](i);
}

cout << "Topological Order:\n";

while (![Link]()) {
int u = [Link]();

4
[Link]();
cout << u << " ";

for (int v : adj[u]) {


indegree[v]--;
if (indegree[v] == 0)
[Link](v);
}
}
}

int main() {
int V, E;
cout << "Enter number of vertices and edges: ";
cin >> V >> E;

vector<vector<int>> adj(V);

cout << "Enter edges (u v):\n";


for (int i = 0; i < E; i++) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
}

topologicalSort(V, adj);

return 0;
}

2. Implementation of BFS using queue and DFS using stack and in both
implementations use linked list to store adjacency list of each node
BFS (Queue) + DFS (Stack) using Linked List (C++)

#include <iostream>
#include <list>
#include <queue>
#include <stack>
using namespace std;

class Graph {
int V; // Number of vertices

5
list<int>* adj; // Adjacency list using linked list

public:
Graph(int V) {
this->V = V;
adj = new list<int>[V];
}

// Add edge (directed graph)


void addEdge(int u, int v) {
adj[u].push_back(v);
}

// BFS using Queue


void BFS(int start) {
bool* visited = new bool[V];

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


visited[i] = false;

queue<int> q;
visited[start] = true;
[Link](start);

cout << "BFS Traversal: ";

while (![Link]()) {
int node = [Link]();
[Link]();
cout << node << " ";

for (int neighbor : adj[node]) {


if (!visited[neighbor]) {
visited[neighbor] = true;
[Link](neighbor);
}
}
}
cout << endl;
}

6
// DFS using Stack (Iterative)
void DFS(int start) {
bool* visited = new bool[V];

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


visited[i] = false;

stack<int> st;
[Link](start);

cout << "DFS Traversal: ";

while (![Link]()) {
int node = [Link]();
[Link]();

if (!visited[node]) {
cout << node << " ";
visited[node] = true;

// Push neighbors
for (int neighbor : adj[node]) {
if (!visited[neighbor])
[Link](neighbor);
}
}
}
cout << endl;
}
};

int main() {
int V, E;
cout << "Enter number of vertices: ";
cin >> V;

Graph g(V);

cout << "Enter number of edges: ";


cin >> E;

cout << "Enter edges (u v):\n";


for (int i = 0; i < E; i++) {

7
int u, v;
cin >> u >> v;
[Link](u, v);
}

int start;
cout << "Enter starting vertex: ";
cin >> start;

[Link](start);
[Link](start);

return 0;
}

3. Implementation of strongly connected components (Kosaraju’s Algorithm in


C++)

#include <iostream>
#include <vector>
#include <stack>
using namespace std;

class Graph {
int V;
vector<vector<int>> adj;

public:
Graph(int V) {
this->V = V;
[Link](V);
}

void addEdge(int u, int v) {


adj[u].push_back(v);
}

// Step 1: DFS to fill stack


void fillOrder(int v, vector<bool>& visited, stack<int>& st) {
visited[v] = true;

8
for (int u : adj[v]) {
if (!visited[u])
fillOrder(u, visited, st);
}

[Link](v);
}

// Step 2: Transpose graph


Graph getTranspose() {
Graph g(V);
for (int v = 0; v < V; v++) {
for (int u : adj[v]) {
[Link][u].push_back(v);
}
}
return g;
}

// Step 3: DFS on transposed graph


void DFS(int v, vector<bool>& visited) {
visited[v] = true;
cout << v << " ";

for (int u : adj[v]) {


if (!visited[u])
DFS(u, visited);
}
}

// Main function to print SCCs


void printSCCs() {
stack<int> st;
vector<bool> visited(V, false);

// Fill stack with finishing times


for (int i = 0; i < V; i++) {
if (!visited[i])
fillOrder(i, visited, st);
}

// Create transpose graph

9
Graph gr = getTranspose();

// Mark all vertices as not visited again


fill([Link](), [Link](), false);

cout << "Strongly Connected Components:\n";

// Process all vertices in order defined by stack


while (![Link]()) {
int v = [Link]();
[Link]();

if (!visited[v]) {
[Link](v, visited);
cout << endl;
}
}
}
};

int main() {
int V, E;
cout << "Enter number of vertices: ";
cin >> V;

Graph g(V);

cout << "Enter number of edges: ";


cin >> E;

cout << "Enter edges (u v):\n";


for (int i = 0; i < E; i++) {
int u, v;
cin >> u >> v;
[Link](u, v);
}

[Link]();

return 0;
}

10
Sample Input
Enter number of vertices: 5
Enter number of edges: 5
02
21
10
03
34

Output
Strongly Connected Components:
012
3
4

4. Implementation of Minimum Spanning Trees


Minimum Spanning Tree (MST), examines usually two standard algorithms
Prim’s Algorithm (greedy, uses priority queue)
Kruskal’s Algorithm (greedy, uses sorting + disjoint set)

Prim’s Algorithm (Using Priority Queue)


#include <iostream>
#include <vector>
#include <queue>
using namespace std;

typedef pair<int, int> pii; // (weight, vertex)

void primMST(int V, vector<vector<pii>>& adj) {


priority_queue<pii, vector<pii>, greater<pii>> pq;
vector<bool> inMST(V, false);

[Link]({0, 0}); // {weight, start vertex}


int totalCost = 0;

cout << "Edges in MST:\n";

while (![Link]()) {
int weight = [Link]().first;
int u = [Link]().second;

11
[Link]();

if (inMST[u]) continue;

inMST[u] = true;
totalCost += weight;

cout << "Include vertex: " << u << " with weight " << weight << endl;

for (auto edge : adj[u]) {


int v = [Link];
int w = [Link];

if (!inMST[v]) {
[Link]({w, v});
}
}
}

cout << "Total cost of MST: " << totalCost << endl;
}

int main() {
int V, E;
cout << "Enter number of vertices and edges: ";
cin >> V >> E;

vector<vector<pii>> adj(V);

cout << "Enter edges (u v weight):\n";


for (int i = 0; i < E; i++) {
int u, v, w;
cin >> u >> v >> w;

adj[u].push_back({v, w});
adj[v].push_back({u, w}); // undirected graph
}

primMST(V, adj);
return 0;
}

12
Kruskal’s Algorithm (Using Disjoint Set / Union-Find)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

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

bool cmp(Edge a, Edge b) {


return [Link] < [Link];
}

class DSU {
vector<int> parent, rank;

public:
DSU(int n) {
[Link](n);
[Link](n, 0);
for (int i = 0; i < n; i++)
parent[i] = i;
}

int find(int x) {
if (parent[x] != x)
parent[x] = find(parent[x]);
return parent[x];
}

void unite(int x, int y) {


int px = find(x);
int py = find(y);

if (px == py) return;

if (rank[px] < rank[py])


parent[px] = py;
else if (rank[px] > rank[py])
parent[py] = px;
else {
parent[py] = px;

13
rank[px]++;
}
}
};

void kruskalMST(int V, vector<Edge>& edges) {


sort([Link](), [Link](), cmp);

DSU dsu(V);
int totalCost = 0;

cout << "Edges in MST:\n";

for (auto e : edges) {


if ([Link](e.u) != [Link](e.v)) {
[Link](e.u, e.v);
cout << e.u << " - " << e.v << " : " << [Link] << endl;
totalCost += [Link];
}
}

cout << "Total cost of MST: " << totalCost << endl;
}

int main() {
int V, E;
cout << "Enter number of vertices and edges: ";
cin >> V >> E;

vector<Edge> edges(E);

cout << "Enter edges (u v weight):\n";


for (int i = 0; i < E; i++) {
cin >> edges[i].u >> edges[i].v >> edges[i].weight;
}

kruskalMST(V, edges);
return 0;
}

14
5. Implementation of Maximum Sub-Array Problem, Stassen’s Matrix Multiplication
Maximum Subarray Problem (Kadane’s Algorithm)
This solves the problem of finding the contiguous subarray with the largest sum in O(n)
time.

#include <iostream>
#include <vector>
using namespace std;

int maxSubArray(vector<int>& nums) {


int max_so_far = nums[0];
int current_sum = nums[0];

for (int i = 1; i < [Link](); i++) {


current_sum = max(nums[i], current_sum + nums[i]);
max_so_far = max(max_so_far, current_sum);
}

return max_so_far;
}

int main() {
vector<int> arr = {-2, 1, -3, 4, -1, 2, 1, -5, 4};

cout << "Maximum Subarray Sum: " << maxSubArray(arr) << endl;
return 0;
}

Strassen’s Matrix Multiplication


Strassen’s algorithm multiplies matrices faster than the naive method:
Time Complexity ≈ O(n^2.81)
#include <iostream>
#include <vector>
using namespace std;

typedef vector<vector<int>> Matrix;

// Add two matrices


Matrix add(Matrix A, Matrix B) {
int n = [Link]();
Matrix C(n, vector<int>(n));

15
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
C[i][j] = A[i][j] + B[i][j];
return C;
}

// Subtract two matrices


Matrix subtract(Matrix A, Matrix B) {
int n = [Link]();
Matrix C(n, vector<int>(n));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
C[i][j] = A[i][j] - B[i][j];
return C;
}

// Strassen multiplication
Matrix strassen(Matrix A, Matrix B) {
int n = [Link]();
Matrix C(n, vector<int>(n));

if (n == 1) {
C[0][0] = A[0][0] * B[0][0];
return C;
}

int k = n / 2;

Matrix A11(k, vector<int>(k)), A12(k, vector<int>(k)),


A21(k, vector<int>(k)), A22(k, vector<int>(k));
Matrix B11(k, vector<int>(k)), B12(k, vector<int>(k)),
B21(k, vector<int>(k)), B22(k, vector<int>(k));

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

B11[i][j] = B[i][j];
B12[i][j] = B[i][j + k];

16
B21[i][j] = B[i + k][j];
B22[i][j] = B[i + k][j + k];
}
}

// 7 multiplications
Matrix M1 = strassen(add(A11, A22), add(B11, B22));
Matrix M2 = strassen(add(A21, A22), B11);
Matrix M3 = strassen(A11, subtract(B12, B22));
Matrix M4 = strassen(A22, subtract(B21, B11));
Matrix M5 = strassen(add(A11, A12), B22);
Matrix M6 = strassen(subtract(A21, A11), add(B11, B12));
Matrix M7 = strassen(subtract(A12, A22), add(B21, B22));

// Combine results
Matrix C11 = add(subtract(add(M1, M4), M5), M7);
Matrix C12 = add(M3, M5);
Matrix C21 = add(M2, M4);
Matrix C22 = add(subtract(add(M1, M3), M2), M6);

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

return C;
}

// Print matrix
void printMatrix(Matrix A) {
for (auto row : A) {
for (auto val : row)
cout << val << " ";
cout << endl;
}
}

17
int main() {
Matrix A = {{1, 2}, {3, 4}};
Matrix B = {{5, 6}, {7, 8}};

Matrix C = strassen(A, B);

cout << "Result Matrix:\n";


printMatrix(C);

return 0;
}

6. Implementation of Shortest Path Algorithms


a) Dijkstra’s Algorithm (Greedy, no negative weights)
Best for: Non-negative weighted graphs (most common case)

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> pii;

void dijkstra(int V, vector<vector<pii>>& adj, int src) {


vector<int> dist(V, INT_MAX);
priority_queue<pii, vector<pii>, greater<pii>> pq;

dist[src] = 0;
[Link]({0, src});

while (![Link]()) {
int u = [Link]().second;
int d = [Link]().first;
[Link]();

if (d > dist[u]) continue;

for (auto edge : adj[u]) {


int v = [Link];
int weight = [Link];

if (dist[u] + weight < dist[v]) {

18
dist[v] = dist[u] + weight;
[Link]({dist[v], v});
}
}
}

cout << "Vertex Distance from Source:\n";


for (int i = 0; i < V; i++)
cout << i << " -> " << dist[i] << endl;
}

b) Bellman-Ford Algorithm (handles negative weights)


Best for: Graphs with negative weights and detecting negative cycles
#include <bits/stdc++.h>
using namespace std;

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

void bellmanFord(int V, int E, vector<Edge>& edges, int src) {


vector<int> dist(V, INT_MAX);
dist[src] = 0;

// Relax edges V-1 times


for (int i = 1; i < V; i++) {
for (auto edge : edges) {
if (dist[edge.u] != INT_MAX &&
dist[edge.u] + edge.w < dist[edge.v]) {
dist[edge.v] = dist[edge.u] + edge.w;
}
}
}

// Check for negative cycles


for (auto edge : edges) {
if (dist[edge.u] != INT_MAX &&
dist[edge.u] + edge.w < dist[edge.v]) {
cout << "Negative weight cycle detected\n";
return;
}

19
}

cout << "Vertex Distance from Source:\n";


for (int i = 0; i < V; i++)
cout << i << " -> " << dist[i] << endl;
}

c) Floyd-Warshall Algorithm (All-Pairs Shortest Path)


Best for: Finding shortest paths between all pairs (dense graphs)

#include <bits/stdc++.h>
using namespace std;

#define INF 1e9

void floydWarshall(vector<vector<int>>& graph, int V) {


vector<vector<int>> dist = graph;

for (int k = 0; k < V; k++) {


for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (dist[i][k] < INF && dist[k][j] < INF)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}

cout << "Shortest distances between all pairs:\n";


for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (dist[i][j] == INF)
cout << "INF ";
else
cout << dist[i][j] << " ";
}
cout << endl;
}
}

Example Graph Input (for testing)


int main() {
int V = 5;

20
vector<vector<pair<int,int>>> adj(V);

adj[0].push_back({1, 2});
adj[0].push_back({2, 4});
adj[1].push_back({2, 1});
adj[1].push_back({3, 7});
adj[2].push_back({4, 3});
adj[3].push_back({4, 1});

dijkstra(V, adj, 0);

return 0;
}

7. Implementation of Longest Common Subsequence.


A. LCS Length (Dynamic Programming)
Build a DP table where dp[i][j] = LCS length of first i chars of string A and first j chars
of string B
#include <bits/stdc++.h>
using namespace std;

int lcsLength(string X, string Y) {


int m = [Link]();
int n = [Link]();

vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

for (int i = 1; i <= m; i++) {


for (int j = 1; j <= n; j++) {
if (X[i - 1] == Y[j - 1])
dp[i][j] = 1 + dp[i - 1][j - 1];
else
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}

return dp[m][n];
}

21
B. Print the Actual LCS
To reconstruct the subsequence, it will trace back from dp[m][n].

#include <bits/stdc++.h>
using namespace std;

string lcs(string X, string Y) {


int m = [Link]();
int n = [Link]();

vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

// Build DP table
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (X[i - 1] == Y[j - 1])
dp[i][j] = 1 + dp[i - 1][j - 1];
else
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}

// Reconstruct LCS
int i = m, j = n;
string lcsStr = "";

while (i > 0 && j > 0) {


if (X[i - 1] == Y[j - 1]) {
lcsStr += X[i - 1];
i--; j--;
}
else if (dp[i - 1][j] > dp[i][j - 1]) {
i--;
} else {
j--;
}
}

reverse([Link](), [Link]());
return lcsStr;
}

22
C. Example Usage
int main() {
string X = "AGGTAB";
string Y = "GXTXAYB";

cout << "LCS Length: " << lcsLength(X, Y) << endl;


cout << "LCS String: " << lcs(X, Y) << endl;

return 0;
}
Output:
LCS Length: 4
LCS String: GTAB

8. Implementation of Matrix Chain Multiplication, Simplex Algorithm, Floyd-


Warshall algorithm.
A. Matrix Chain Multiplication (MCM)
Find minimum number of scalar multiplications needed to multiply a chain of matrices.

DP Approach
#include <bits/stdc++.h>
using namespace std;

int matrixChainMultiplication(vector<int>& p) {
int n = [Link](); // number of matrices = n-1
vector<vector<int>> dp(n, vector<int>(n, 0));

for (int len = 2; len < n; len++) {


for (int i = 1; i < n - len + 1; i++) {
int j = i + len - 1;
dp[i][j] = INT_MAX;

for (int k = i; k < j; k++) {


int cost = dp[i][k] + dp[k+1][j] + p[i-1]*p[k]*p[j];
dp[i][j] = min(dp[i][j], cost);
}
}
}

return dp[1][n-1];
}

23
B. Simplex Algorithm (Linear Programming)
Solve linear programming problems of form
Maximize: Z = c1x1 + c2x2 + ...
Subject to constraints.

#include <bits/stdc++.h>
using namespace std;

const int MAX = 20;

double tableau[MAX][MAX];
int m, n; // m constraints, n variables

void pivot(int row, int col) {


double pivot = tableau[row][col];

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


tableau[row][j] /= pivot;

for (int i = 0; i <= m; i++) {


if (i != row) {
double factor = tableau[i][col];
for (int j = 0; j <= n; j++)
tableau[i][j] -= factor * tableau[row][j];
}
}
}

bool simplex() {
while (true) {
int pivotCol = -1;
for (int j = 0; j < n; j++) {
if (tableau[m][j] < 0) {
pivotCol = j;
break;
}
}
if (pivotCol == -1) return true; // optimal

int pivotRow = -1;


double minRatio = 1e9;

24
for (int i = 0; i < m; i++) {
if (tableau[i][pivotCol] > 0) {
double ratio = tableau[i][n] / tableau[i][pivotCol];
if (ratio < minRatio) {
minRatio = ratio;
pivotRow = i;
}
}
}

if (pivotRow == -1) return false; // unbounded

pivot(pivotRow, pivotCol);
}
}

C. Floyd-Warshall Algorithm (All-Pairs Shortest Path)


Find shortest distances between all pairs of vertices.
#include <bits/stdc++.h>
using namespace std;

#define INF 1e9

void floydWarshall(vector<vector<int>>& graph) {


int V = [Link]();
vector<vector<int>> dist = graph;

for (int k = 0; k < V; k++) {


for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (dist[i][k] < INF && dist[k][j] < INF)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}

cout << "Shortest distance matrix:\n";


for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (dist[i][j] == INF)
cout << "INF ";

25
else
cout << dist[i][j] << " ";
}
cout << endl;
}
}

Example Usage
int main() {
// Matrix Chain Multiplication
vector<int> dims = {10, 20, 30, 40};
cout << "MCM Min Cost: " << matrixChainMultiplication(dims) << endl;

// Floyd-Warshall
vector<vector<int>> graph = {
{0, 3, INF, 5},
{2, 0, INF, 4},
{INF, 1, 0, INF},
{INF, INF, 2, 0}
};

floydWarshall(graph);

return 0;
}

26

You might also like