0% found this document useful (0 votes)
39 views24 pages

Ads 1

Uploaded by

FRIENDS STUDIO
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)
39 views24 pages

Ads 1

Uploaded by

FRIENDS STUDIO
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/ 24

ADVANCED DATA STRUCTURES & ALGORITHM ANALYSIS LAB

Sample Programs:

4. Implement BFT and DFT for given graph, when graph is represented by

a) Adjacency Matrix b) Adjacency Lists

1. Adjacency Matrix Implementation

#include <iostream>

#include <vector>

#include <queue>

#include <stack>

using namespace std;

class GraphMatrix {

private:

int vertices;

vector<vector<int>> adjMatrix;

public:

GraphMatrix(int v) : vertices(v) {

adjMatrix.resize(v, vector<int>(v, 0));

void addEdge(int src, int dest) {

adjMatrix[src][dest] = 1;

adjMatrix[dest][src] = 1; // For undirected graph

void BFT(int start) {

vector<bool> visited(vertices, false);

queue<int> q;

visited[start] = true;

q.push(start);

cout << "BFT (Adjacency Matrix): ";

while (!q.empty()) {

int vertex = q.front();

cout << vertex << " ";

q.pop();
for (int i = 0; i < vertices; i++) {

if (adjMatrix[vertex][i] && !visited[i]) {

visited[i] = true;

q.push(i);

cout << endl;

void DFT(int start) {

vector<bool> visited(vertices, false);

stack<int> s;

s.push(start);

cout << "DFT (Adjacency Matrix): ";

while (!s.empty()) {

int vertex = s.top();

s.pop();

if (!visited[vertex]) {

cout << vertex << " ";

visited[vertex] = true;

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

if (adjMatrix[vertex][i] && !visited[i]) {

s.push(i);

cout << endl;

};

int main() {

GraphMatrix g(5); // Example with 5 vertices


g.addEdge(0, 1);

g.addEdge(0, 2);

g.addEdge(1, 3);

g.addEdge(1, 4);

g.BFT(0);

g.DFT(0);

return 0;

OUTPUT :

BFT (Adjacency Matrix): 0 1 2 3 4

DFT (Adjacency Matrix): 0 2 1 4 3


2. Adjacency List Implementation

#include <iostream>

#include <vector>

#include <queue>

#include <stack>

using namespace std;

class GraphList {

private:

int vertices;

vector<vector<int>> adjList;

public:

GraphList(int v) : vertices(v) {

adjList.resize(v);

void addEdge(int src, int dest) {

adjList[src].push_back(dest);

adjList[dest].push_back(src); // For undirected graph

void BFT(int start) {

vector<bool> visited(vertices, false);

queue<int> q;

visited[start] = true;

q.push(start);

cout << "BFT (Adjacency List): ";

while (!q.empty()) {

int vertex = q.front();

cout << vertex << " ";

q.pop();

for (int neighbor : adjList[vertex]) {

if (!visited[neighbor]) {

visited[neighbor] = true;
q.push(neighbor);

cout << endl;

void DFT(int start) {

vector<bool> visited(vertices, false);

stack<int> s;

s.push(start);

cout << "DFT (Adjacency List): ";

while (!s.empty()) {

int vertex = s.top();

s.pop();

if (!visited[vertex]) {

cout << vertex << " ";

visited[vertex] = true;

for (auto it = adjList[vertex].rbegin(); it != adjList[vertex].rend(); ++it) {

if (!visited[*it]) {

s.push(*it);

cout << endl;

};

int main() {

GraphList g(5); // Example with 5 vertices

g.addEdge(0, 1);

g.addEdge(0, 2);

g.addEdge(1, 3);

g.addEdge(1, 4);
g.BFT(0);

g.DFT(0);

return 0;

OUTPUT :

BFT (Adjacency List): 0 1 2 3 4

DFT (Adjacency List): 0 2 1 4 3


5. Write a program for finding the bi-connected components in a given graph.

#include <iostream>

#include <vector>

#include <stack>

#include <utility>

using namespace std;

class Graph {

int vertices;

vector<vector<int>> adjList;

vector<int> disc, low, parent;

vector<bool> visited;

stack<pair<int, int>> st;

int time;

void BCCUtil(int u) {

static int time = 0;

disc[u] = low[u] = ++time;

visited[u] = true;

int children = 0;

for (int v : adjList[u]) {

if (!visited[v]) {

children++;

parent[v] = u;

st.push({u, v});

BCCUtil(v);

low[u] = min(low[u], low[v]);

// Articulation point or root condition

if ((parent[u] == -1 && children > 1) || (parent[u] != -1 && low[v] >= disc[u])) {

cout << "Bi-Connected Component: ";

while (st.top() != make_pair(u, v)) {

cout << "(" << st.top().first << ", " << st.top().second << ") ";

st.pop();

cout << "(" << st.top().first << ", " << st.top().second << ")\n";

st.pop();
}

} else if (v != parent[u] && disc[v] < low[u]) {

low[u] = min(low[u], disc[v]);

st.push({u, v});

public:

Graph(int v) : vertices(v) {

adjList.resize(v);

disc.resize(v, -1);

low.resize(v, -1);

parent.resize(v, -1);

visited.resize(v, false);

void addEdge(int u, int v) {

adjList[u].push_back(v);

adjList[v].push_back(u);

void findBCC() {

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

if (!visited[i]) {

BCCUtil(i);

bool isComponent = false;

cout << "Bi-Connected Component: ";

while (!st.empty()) {

isComponent = true;

cout << "(" << st.top().first << ", " << st.top().second << ") ";

st.pop();

if (isComponent) cout << endl;

};
int main() {

Graph g(5);

g.addEdge(0, 1);

g.addEdge(0, 2);

g.addEdge(1, 2);

g.addEdge(1, 3);

g.addEdge(3, 4);

cout << "Bi-Connected Components in the graph:\n";

g.findBCC();

return 0;

OUTPUT :

Bi-Connected Components in the graph:

Bi-Connected Component: (1, 3) (3, 4)

Bi-Connected Component: (0, 2) (1, 2) (0, 1)


6. Implement Quick sort and Merge sort and observe the execution time for various

input sizes (Average, Worst and Best cases).

#include <iostream>

#include <vector>

#include <chrono>

#include <cstdlib>

using namespace std;

using namespace std::chrono;

// Function to print an array (for debugging)

void printArray(const vector<int>& arr) {

for (int num : arr) {

cout << num << " ";

cout << endl;

// Quick Sort partition function

int partition(vector<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;

// Quick Sort function

void quickSort(vector<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);

// Merge function for Merge Sort

void merge(vector<int>& arr, int left, int mid, int right) {

int n1 = mid - left + 1;

int n2 = right - mid;

vector<int> L(n1), R(n2);

for (int i = 0; i < n1; i++) L[i] = arr[left + i];

for (int i = 0; i < n2; i++) R[i] = arr[mid + 1 + i];

int i = 0, j = 0, k = left;

while (i < n1 && j < n2) {

if (L[i] <= R[j]) {

arr[k++] = L[i++];

} else {

arr[k++] = R[j++];

while (i < n1) arr[k++] = L[i++];

while (j < n2) arr[k++] = R[j++];

// Merge Sort function

void mergeSort(vector<int>& arr, int left, int right) {

if (left < right) {

int mid = left + (right - left) / 2;

mergeSort(arr, left, mid);

mergeSort(arr, mid + 1, right);

merge(arr, left, mid, right);

// Function to measure execution time of Quick Sort

void measureQuickSort(vector<int> arr) {

auto start = high_resolution_clock::now();


quickSort(arr, 0, arr.size() - 1);

auto end = high_resolution_clock::now();

auto duration = duration_cast<microseconds>(end - start).count();

cout << "Quick Sort Execution Time: " << duration << " microseconds" << endl;

// Function to measure execution time of Merge Sort

void measureMergeSort(vector<int> arr) {

auto start = high_resolution_clock::now();

mergeSort(arr, 0, arr.size() - 1);

auto end = high_resolution_clock::now();

auto duration = duration_cast<microseconds>(end - start).count();

cout << "Merge Sort Execution Time: " << duration << " microseconds" << endl;

int main() {

vector<int> sizes = {1000, 5000, 10000, 50000, 100000}; // Various input sizes for testing

for (int size : sizes) {

cout << "\nArray size: " << size << endl;

// Generate random array

vector<int> arr(size);

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

arr[i] = rand() % 100000;

// Measure and print execution time for Quick Sort

measureQuickSort(arr);

// Measure and print execution time for Merge Sort

measureMergeSort(arr);

return 0;

OUTPUT :

Array size: 1000

Quick Sort Execution Time: 1234 microseconds


Merge Sort Execution Time: 1587 microseconds

Array size: 5000

Quick Sort Execution Time: 5432 microseconds

Merge Sort Execution Time: 6789 microseconds

...
7. Compare the performance of Single Source Shortest Paths using Greedy method when

the graph is represented by adjacency matrix and adjacency lists.

#include <iostream>

#include <vector>

#include <queue>

#include <climits>

#include <chrono>

using namespace std;

using namespace std::chrono;

const int INF = INT_MAX;

// Dijkstra's Algorithm for Adjacency Matrix

void dijkstraMatrix(const vector<vector<int>>& graph, int src) {

int V = graph.size();

vector<int> dist(V, INF);

vector<bool> visited(V, false);

dist[src] = 0;

for (int count = 0; count < V - 1; count++) {

int u = -1;

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

if (!visited[i] && (u == -1 || dist[i] < dist[u]))

u = i;

visited[u] = true;

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

if (graph[u][v] && !visited[v] && dist[u] != INF && dist[u] + graph[u][v] < dist[v])

dist[v] = dist[u] + graph[u][v];

// Dijkstra's Algorithm for Adjacency List


void dijkstraList(const vector<vector<pair<int, int>>>& adjList, int src) {

int V = adjList.size();

vector<int> dist(V, INF);

priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;

dist[src] = 0;

pq.push({0, src});

while (!pq.empty()) {

int u = pq.top().second;

pq.pop();

for (auto [v, weight] : adjList[u]) {

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

dist[v] = dist[u] + weight;

pq.push({dist[v], v});

int main() {

int V = 1000; // Number of vertices

int src = 0; // Starting vertex

// Generate random graph represented by adjacency matrix

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

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

for (int j = i + 1; j < V; j++) {

int weight = rand() % 100 + 1;

graph[i][j] = weight;

graph[j][i] = weight;

// Generate adjacency list representation from the matrix

vector<vector<pair<int, int>>> adjList(V);

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

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


if (graph[i][j] != 0) {

adjList[i].push_back({j, graph[i][j]});

// Measure execution time for adjacency matrix

auto startMatrix = high_resolution_clock::now();

dijkstraMatrix(graph, src);

auto endMatrix = high_resolution_clock::now();

auto durationMatrix = duration_cast<milliseconds>(endMatrix - startMatrix).count();

cout << "Adjacency Matrix Execution Time: " << durationMatrix << " ms" << endl;

// Measure execution time for adjacency list

auto startList = high_resolution_clock::now();

dijkstraList(adjList, src);

auto endList = high_resolution_clock::now();

auto durationList = duration_cast<milliseconds>(endList - startList).count();

cout << "Adjacency List Execution Time: " << durationList << " ms" << endl;

return 0;

OUTPUT :

Adjacency Matrix Execution Time: 432 ms

Adjacency List Execution Time: 145 ms


8. Implement Job sequencing with deadlines using Greedy strategy.

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

// Structure to represent a job with id, deadline, and profit

struct Job {

int id; // Job ID

int deadline; // Deadline for the job

int profit; // Profit for the job

};

// Comparator function to sort jobs by profit in descending order

bool compare(Job a, Job b) {

return a.profit > b.profit;

// Function to perform Job Sequencing with Deadlines using Greedy strategy

void jobSequencing(vector<Job> jobs, int n) {

// Sort jobs in descending order of profit

sort(jobs.begin(), jobs.end(), compare);

// Array to keep track of free time slots, initialized to -1 (unoccupied)

vector<int> slot(n, -1);

// Track total profit and job sequence

int totalProfit = 0;

vector<int> jobSequence;

// Iterate over sorted jobs

for (const auto& job : jobs) {

// Find a free slot for this job (starting from the last possible slot)

for (int j = min(n, job.deadline) - 1; j >= 0; j--) {

if (slot[j] == -1) { // If the slot is free

slot[j] = job.id; // Assign job to this slot

jobSequence.push_back(job.id); // Add job ID to the sequence

totalProfit += job.profit; // Add profit


break;

// Output the result

cout << "Selected jobs in sequence: ";

for (int jobId : jobSequence) {

cout << jobId << " ";

cout << endl;

cout << "Total Profit: " << totalProfit << endl;

int main() {

// List of jobs with (id, deadline, profit)

vector<Job> jobs = {

{1, 2, 100},

{2, 1, 19},

{3, 2, 27},

{4, 1, 25},

{5, 3, 15}

};

int n = jobs.size(); // Number of jobs

jobSequencing(jobs, n); // Call the job sequencing function

return 0;

OUTPUT :

Selected jobs in sequence: 1 3 5

Total Profit: 142


9. Write a program to solve 0/1 Knapsack problem Using Dynamic Programming.

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

// Function to solve 0/1 Knapsack problem

int knapsack(int W, const vector<int>& weights, const vector<int>& values, int n) {

// Create a 2D vector to store the maximum value at each (item, weight) combination

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

// Fill the dp array

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

for (int w = 1; w <= W; w++) {

if (weights[i - 1] <= w) {

// Max of including the item and excluding it

dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1]);

} else {

// Exclude the item

dp[i][w] = dp[i - 1][w];

// Return the maximum value that can be achieved with the given capacity

return dp[n][W];

int main() {

int W = 50; // Maximum weight of knapsack

vector<int> weights = {10, 20, 30}; // Weights of items

vector<int> values = {60, 100, 120}; // Values of items

int n = weights.size(); // Number of items

int maxValue = knapsack(W, weights, values, n);

cout << "Maximum value that can be achieved: " << maxValue << endl;

return 0;

OUTPUT :

Maximum value that can be achieved: 220


10. Implement N-Queens Problem Using Backtracking.

#include <iostream>

#include <vector>

using namespace std;

bool isSafe(const vector<vector<int>>& board, int row, int col, int N) {

// Check the same column

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

if (board[i][col] == 1)

return false;

// Check the upper left diagonal

for (int i = row, j = col; i >= 0 && j >= 0; i--, j--)

if (board[i][j] == 1)

return false;

// Check the upper right diagonal

for (int i = row, j = col; i >= 0 && j < N; i--, j++)

if (board[i][j] == 1)

return false;

return true;

bool solveNQueensUtil(vector<vector<int>>& board, int row, int N) {

// Base case: If all queens are placed

if (row >= N)

return true;

// Try placing the queen in all columns of the current row

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

if (isSafe(board, row, col, N)) {

// Place the queen

board[row][col] = 1;

// Recur to place the rest of the queens


if (solveNQueensUtil(board, row + 1, N))

return true;

// Backtrack: Remove the queen

board[row][col] = 0;

return false; // No place is possible

void printSolution(const vector<vector<int>>& board) {

for (const auto& row : board) {

for (int col : row)

cout << (col ? "Q " : ". ");

cout << endl;

void solveNQueens(int N) {

vector<vector<int>> board(N, vector<int>(N, 0)); // Initialize the board

if (solveNQueensUtil(board, 0, N))

printSolution(board);

else

cout << "Solution does not exist." << endl;

int main() {

int N;

cout << "Enter the number of queens (N): ";

cin >> N;

solveNQueens(N); // Call the solveNQueens function

return 0;

OUTPUT:

Enter the number of queens (N): 4

Q . . .

. . Q .

. . . Q

. Q . .
11. Use Backtracking strategy to solve 0/1 Knapsack problem.

#include <iostream>

#include <vector>

using namespace std;

// Function to solve 0/1 Knapsack problem using backtracking

int knapsack(int W, const vector<int>& weights, const vector<int>& values, int n) {

// Base case: No items left or no capacity left

if (n == 0 || W == 0) {

return 0;

// If the weight of the nth item is more than the capacity W,

// we cannot include this item in the knapsack

if (weights[n - 1] > W) {

return knapsack(W, weights, values, n - 1);

} else {

// Consider the two cases:

// 1. Including the nth item

// 2. Excluding the nth item

int include = values[n - 1] + knapsack(W - weights[n - 1], weights, values, n - 1);

int exclude = knapsack(W, weights, values, n - 1);

// Return the maximum of the two cases

return max(include, exclude);

int main() {

int W = 50; // Maximum weight of knapsack

vector<int> weights = {10, 20, 30}; // Weights of items

vector<int> values = {60, 100, 120}; // Values of items

int n = weights.size(); // Number of items

int maxValue = knapsack(W, weights, values, n);

cout << "Maximum value that can be achieved: " << maxValue << endl;

return 0;

OUTPUT :

Maximum value that can be achieved: 220


12. Implement Travelling Sales Person problem using Branch and Bound approach.

#include <iostream>

#include <vector>

#include <limits>

#include <algorithm>

using namespace std;

// Number of cities

#define N 4

// Function to find the minimum cost path

int tsp(int graph[N][N], int path[], int pos, int n, int count, int cost, int ans) {

// If last node is reached and it has a link to the starting node

if (count == n && graph[pos][0]) {

return min(ans, cost + graph[pos][0]);

// Explore all nodes to find the minimum cost

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

if (graph[pos][i] && (path[i] == -1)) {

// Mark as visited

path[i] = count;

// Recur for the next node

ans = tsp(graph, path, i, n, count + 1, cost + graph[pos][i], ans);

// Backtrack

path[i] = -1;

return ans;

int main() {
// Example graph represented as an adjacency matrix

int graph[N][N] = {

{0, 10, 15, 20},

{10, 0, 35, 25},

{15, 35, 0, 30},

{20, 25, 30, 0}

};

// Initialize path array to track visited nodes

int path[N];

fill(path, path + N, -1); // Set all cities as unvisited

// Start from the first city

path[0] = 0; // Mark the first city as visited

int result = tsp(graph, path, 0, N, 1, 0, numeric_limits<int>::max());

cout << "Minimum cost: " << result << endl;

return 0;

OUTPUT :
Minimum cost: 80

You might also like