Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

AADS_pracfile

Download as pdf or txt
Download as pdf or txt
You are on page 1of 27

Algorithm and advanced data structures

Name: Jaspreet singh | Course: B.Sc (Hons) Computer Science | Roll no: 2022CSC1048

Q1. Write a program to sort the elements of an array using Randomized Quick
Sort (the program should report the number of comparisons).
Click here to run the code
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int comparisons = 0;
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
int randomizedPartition(int arr[], int low, int high) {
int pivotIndex = low + rand() % (high - low + 1);
swap(arr[pivotIndex], arr[high]);
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
comparisons++;
if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]);
}
}
swap(arr[i + 1], arr[high]);
return i + 1;
}
void randomizedQuickSort(int arr[], int low, int high) {
if (low < high) {
int pi = randomizedPartition(arr, low, high);
randomizedQuickSort(arr, low, pi - 1);
randomizedQuickSort(arr, pi + 1, high);
}
}
void sortArray(int arr[], int size) {
srand(time(0));
comparisons = 0;
randomizedQuickSort(arr, 0, size - 1);
}
int main() {
int arr[] = {10, 7, 8, 9, 1, 5};
int size = sizeof(arr) / sizeof(arr[0]);
cout << "Original array: ";
printArray(arr, size);
sortArray(arr, size);
cout << "Sorted array: ";
printArray(arr, size);
cout << "Total comparisons: " << comparisons << endl;
return 0;
}

Q2 Write a program to find the ith smallest element of an array using


Randomized Select.
Click here to run the code
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int comparisons = 0;
int randomizedPartition(int arr[], int low, int high) {
int pivotIndex = low + rand() % (high - low + 1);
swap(arr[pivotIndex], arr[high]);
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
comparisons++;
if (arr[j] < pivot) {
i++;
swap(arr[i], arr[j]);
}
}
swap(arr[i + 1], arr[high]);
return i + 1;
}
int randomizedSelect(int arr[], int low, int high, int i) {
if (low == high) return arr[low];
int pivotIndex = randomizedPartition(arr, low, high);
int k = pivotIndex - low + 1;
if (i == k) return arr[pivotIndex];
else if (i < k) return randomizedSelect(arr, low, pivotIndex - 1, i);
else return randomizedSelect(arr, pivotIndex + 1, high, i - k);
}
int main() {
srand(time(0));
int arr[] = {10, 4, 5, 8, 6, 11, 26};
int size = sizeof(arr) / sizeof(arr[0]);
int i = 4;
cout << i << "th smallest element is " << randomizedSelect(arr, 0, size - 1, i)
<< endl;
cout << "Total comparisons: " << comparisons << endl;
return 0;
}

Q3 Write a program to determine the minimum spanning tree of a graph using


Kruskal’s algorithm.
Click here to run the code
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Edge {
int u, v, weight;
bool operator<(const Edge &e) {
return weight < e.weight;
}
};
int find(int parent[], int i) {
if (parent[i] == i) return i;
return parent[i] = find(parent, parent[i]);
}
void unionSets(int parent[], int rank[], int x, int y) {
int rootX = find(parent, x);
int rootY = find(parent, y);
if (rootX != rootY) {
if (rank[rootX] < rank[rootY]) parent[rootX] = rootY;
else if (rank[rootX] > rank[rootY]) parent[rootY] = rootX;
else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
}
int main() {
int vertices = 4, edges = 5;
vector<Edge> edgeList = {
{0, 1, 10},
{0, 2, 6},
{0, 3, 5},
{1, 3, 15},
{2, 3, 4}
};
sort(edgeList.begin(), edgeList.end());
int parent[vertices], rank[vertices];
for (int i = 0; i < vertices; i++) {
parent[i] = i;
rank[i] = 0;
}
vector<Edge> mst;
for (Edge &e : edgeList) {
int uRoot = find(parent, e.u);
int vRoot = find(parent, e.v);
if (uRoot != vRoot) {
mst.push_back(e);
unionSets(parent, rank, uRoot, vRoot);
}
}
cout << "Edges in the minimum spanning tree:\n";
for (Edge &e : mst) {
cout << e.u << " - " << e.v << " : " << e.weight << endl;
}
return 0;
}

Q4 Write a program to implement the Bellman-Ford algorithm to find the


shortest paths
Click here to run the code
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
struct Edge {
int u, v, weight;
};
void bellmanFord(int V, int E, vector<Edge> &edges, int source) {
vector<int> distance(V, INT_MAX);
distance[source] = 0;
for (int i = 1; i < V - 1; i++) {
for (int j = 0; j < E; j++) {
int u = edges[j].u;
int v = edges[j].v;
int weight = edges[j].weight;
if (distance[u] != INT_MAX && distance[u] + weight < distance[v]) {
distance[v] = distance[u] + weight;
}
}
}
for (int i = 0; i < E; i++) {
int u = edges[i].u;
int v = edges[i].v;
int weight = edges[i].weight;
if (distance[u] != INT_MAX && distance[u] + weight < distance[v]) {
cout << "Graph contains negative weight cycle\n";
return;
}
}
for (int i = 0; i < V; i++) {
cout << "Distance from source " << source << " to " << i << " is " <<
distance[i] << endl;
}
}
int main() {
int V = 5, E = 8;
vector<Edge> edges = {
{0, 1, -1}, {0, 2, 4}, {1, 2, 3}, {1, 3, 2}, {1, 4, 2}, {3, 2, 5},
{3, 1, 1}, {4, 3, -3}
};
int source = 0;
bellmanFord(V, E, edges, source);
return 0;
}

Q5 from a given source node to all other nodes in a graph.


Click here to run the code
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define MIN_DEGREE 2
class BTreeNode {
public:
vector<int> keys;
vector<BTreeNode *> children;
bool isLeaf;
int numKeys;
BTreeNode(bool isLeaf);
void insertNonFull(int key);
void splitChild(int i, BTreeNode *y);
void deleteKey(int key);
void deleteFromLeaf(int idx);
void deleteFromNonLeaf(int idx);
int findKey(int key);
void merge(int idx);
void printTree(int level);
};
class BTree {
public:
BTreeNode *root;
BTree();
void insert(int key);
void search(int key);
void remove(int key);
void printTree();
};
BTreeNode::BTreeNode(bool isLeaf) {
this->isLeaf = isLeaf;
this->numKeys = 0;
}
BTree::BTree() {
root = new BTreeNode(true);
}
void BTreeNode::insertNonFull(int key) {
int i = numKeys - 1;
if (isLeaf) {
keys.push_back(0);
while (i >= 0 && keys[i] > key) {
keys[i + 1] = keys[i];
i--;
}
keys[i + 1] = key;
numKeys++;
} else {
while (i >= 0 && keys[i] > key) i--;
if (children[i + 1]->numKeys == 2 * MIN_DEGREE - 1) {
splitChild(i + 1, children[i + 1]);
if (keys[i + 1] < key) i++;
}
children[i + 1]->insertNonFull(key);
}
}
void BTreeNode::splitChild(int i, BTreeNode *y) {
BTreeNode *z = new BTreeNode(y->isLeaf);
z->numKeys = MIN_DEGREE - 1;
for (int j = 0; j < MIN_DEGREE - 1; j++) {
z->keys.push_back(y->keys[j + MIN_DEGREE]);
}
if (!y->isLeaf) {
for (int j = 0; j < MIN_DEGREE; j++) {
z->children.push_back(y->children[j + MIN_DEGREE]);
}
}
y->numKeys = MIN_DEGREE - 1;
children.insert(children.begin() + i + 1, z);
keys.insert(keys.begin() + i, y->keys[MIN_DEGREE - 1]);
numKeys++;
}
void BTreeNode::deleteKey(int key) {
int idx = findKey(key);
if (idx < numKeys && keys[idx] == key) {
if (isLeaf) {
deleteFromLeaf(idx);
} else {
deleteFromNonLeaf(idx);
}
} else {
bool flag = (idx == numKeys);
if (children[idx]->numKeys < MIN_DEGREE) {
merge(idx);
if (flag && idx > numKeys) idx--;
}
children[idx]->deleteKey(key);
}
}
void BTreeNode::deleteFromLeaf(int idx) {
keys.erase(keys.begin() + idx);
numKeys--;
}
void BTreeNode::deleteFromNonLeaf(int idx) {
int key = keys[idx];
if (children[idx]->numKeys >= MIN_DEGREE) {
int pred = children[idx]->keys[children[idx]->numKeys - 1];
keys[idx] = pred;
children[idx]->deleteKey(pred);
} else if (children[idx + 1]->numKeys >= MIN_DEGREE) {
int succ = children[idx + 1]->keys[0];
keys[idx] = succ;
children[idx + 1]->deleteKey(succ);
} else {
merge(idx);
children[idx]->deleteKey(key);
}
}
int BTreeNode::findKey(int key) {
int idx = 0;
while (idx < numKeys && keys[idx] < key) idx++;
return idx;
}
void BTreeNode::merge(int idx) {
BTreeNode *child = children[idx];
BTreeNode *sibling = children[idx + 1];
child->keys.push_back(keys[idx]);
for (int i = 0; i < sibling->numKeys; i++) {
child->keys.push_back(sibling->keys[i]);
}
if (!child->isLeaf) {
for (int i = 0; i < sibling->numKeys + 1; i++) {
child->children.push_back(sibling->children[i]);
}
}
keys.erase(keys.begin() + idx);
children.erase(children.begin() + idx + 1);
child->numKeys += sibling->numKeys + 1;
numKeys--;
}
void BTree::insert(int key) {
if (root->numKeys == 2 * MIN_DEGREE - 1) {
BTreeNode *s = new BTreeNode(false);
s->children.push_back(root);
s->splitChild(0, root);
root = s;
}
root->insertNonFull(key);
}
void BTree::search(int key) {
BTreeNode *node = root;
while (node) {
int idx = node->findKey(key);
if (idx < node->numKeys && node->keys[idx] == key) {
cout << "Found " << key << endl;
return;
} else if (node->isLeaf) {
cout << "Not found " << key << endl;
return;
} else {
node = node->children[idx];
}
}
}
void BTree::remove(int key) {
root->deleteKey(key);
if (root->numKeys == 0) {
if (root->isLeaf) {
root = nullptr;
} else {
root = root->children[0];
}
}
}
void BTreeNode::printTree(int level) {
cout << "Level " << level << ": ";
for (int i = 0; i < numKeys; i++) {
cout << keys[i] << " ";
}
cout << endl;
if (!isLeaf) {
for (int i = 0; i <= numKeys; i++) {
children[i]->printTree(level + 1);
}
}
}
void BTree::printTree() {
root->printTree(0);
}
int main() {
BTree t;
t.insert(10);
t.insert(20);
t.insert(5);
t.insert(6);
t.insert(12);
t.insert(30);
t.insert(7);
cout << "Tree after insertions:" << endl;
t.printTree();
t.remove(10);
cout << "Tree after removing 10:" << endl;
t.printTree();
t.search(10);
t.search(5);
return 0;
}

Q6 Write a program to implement a B-Tree, which supports the following


operations:
a. Insert
b. Search
c. Deletion
Click here to run the code
#include <iostream>
#include <vector>
using namespace std;
struct Node {
vector<int> keys;
vector<Node*> children;
bool isLeaf;
Node(bool leaf) { isLeaf = leaf; }
};
class TwoFourTree {
public:
Node* root;
TwoFourTree() { root = new Node(true); }
Node* search(Node* node, int key) {
int i = 0;
while (i < node->keys.size() && key > node->keys[i]) i++;
if (i < node->keys.size() && key == node->keys[i]) return node;
if (node->isLeaf) return nullptr;
return search(node->children[i], key);
}
bool search(int key) {
Node* result = search(root, key);
return result != nullptr;
}
void insert(int key) {
if (root->keys.size() == 3) {
Node* newRoot = new Node(false);
newRoot->children.push_back(root);
splitChild(newRoot, 0);
root = newRoot;
}
insertNonFull(root, key);
}
void insertNonFull(Node* node, int key) {
int i = node->keys.size() - 1;
if (node->isLeaf) {
while (i >= 0 && key < node->keys[i]) i--;
node->keys.insert(node->keys.begin() + i + 1, key);
} else {
while (i >= 0 && key < node->keys[i]) i--;
i++;
if (node->children[i]->keys.size() == 3) {
splitChild(node, i);
if (key > node->keys[i]) i++;
}
insertNonFull(node->children[i], key);
}
}
void splitChild(Node* parent, int i) {
Node* fullChild = parent->children[i];
Node* newChild = new Node(fullChild->isLeaf);
parent->children.insert(parent->children.begin() + i + 1, newChild);
parent->keys.insert(parent->keys.begin() + i, fullChild->keys[1]);
newChild->keys.push_back(fullChild->keys[2]);
fullChild->keys.resize(1);
if (!fullChild->isLeaf) {
newChild->children.push_back(fullChild->children[2]);
fullChild->children.resize(2);
}
}
void remove(int key) {
remove(root, key);
if (root->keys.empty()) {
Node* temp = root;
root = root->children[0];
delete temp;
}
}
void remove(Node* node, int key) {
int i = 0;
while (i < node->keys.size() && key > node->keys[i]) i++;
if (i < node->keys.size() && key == node->keys[i]) {
if (node->isLeaf) {
node->keys.erase(node->keys.begin() + i);
} else {
removeInternalNode(node, i);
}
} else if (!node->isLeaf) {
if (node->children[i]->keys.size() == 1) {
fill(node, i);
}
if (i < node->keys.size() && key == node->keys[i]) {
remove(node->children[i + 1], key);
} else {
remove(node->children[i], key);
}
}
}
void removeInternalNode(Node* node, int i) {
int key = node->keys[i];
if (node->children[i]->keys.size() >= 2) {
Node* pred = node->children[i];
while (!pred->isLeaf) pred = pred->children[pred->keys.size()];
node->keys[i] = pred->keys[pred->keys.size() - 1];
remove(pred, node->keys[i]);
} else if (node->children[i + 1]->keys.size() >= 2) {
Node* succ = node->children[i + 1];
node->keys[i] = succ->keys[0];
remove(succ, node->keys[i]);
} else {
merge(node, i);
remove(node->children[i], key);
}
}
void merge(Node* node, int i) {
Node* left = node->children[i];
Node* right = node->children[i + 1];
left->keys.push_back(node->keys[i]);
left->keys.insert(left->keys.end(), right->keys.begin(), right->keys.end());
if (!left->isLeaf) {
left->children.insert(left->children.end(), right->children.begin(),
right->children.end());
}
node->keys.erase(node->keys.begin() + i);
node->children.erase(node->children.begin() + i + 1);
delete right;
}
void fill(Node* node, int i) {
if (i > 0 && node->children[i - 1]->keys.size() > 1) {
borrowFromPrev(node, i);
} else if (i < node->keys.size() && node->children[i + 1]->keys.size() > 1) {
borrowFromNext(node, i);
} else {
if (i < node->keys.size()) {
merge(node, i);
} else {
merge(node, i - 1);
}
}
}
void borrowFromPrev(Node* node, int i) {
Node* child = node->children[i];
Node* sibling = node->children[i - 1];
child->keys.insert(child->keys.begin(), node->keys[i - 1]);
node->keys[i - 1] = sibling->keys[sibling->keys.size() - 1];
sibling->keys.pop_back();
if (!sibling->isLeaf) {
child->children.insert(child->children.begin(),
sibling->children[sibling->children.size() - 1]);
sibling->children.pop_back();
}
}
void borrowFromNext(Node* node, int i) {
Node* child = node->children[i];
Node* sibling = node->children[i + 1];
child->keys.push_back(node->keys[i]);
node->keys[i] = sibling->keys[0];
sibling->keys.erase(sibling->keys.begin());
if (!sibling->isLeaf) {
child->children.push_back(sibling->children[0]);
sibling->children.erase(sibling->children.begin());
}
}
};
int main() {
TwoFourTree tree;
tree.insert(10);
tree.insert(20);
tree.insert(5);
tree.insert(6);
tree.insert(15);
tree.insert(30);
tree.insert(25);
cout << "Search for 15: " << (tree.search(15) ? "Found" : "Not Found") << endl;
tree.remove(15);
cout << "Search for 15 after removal: " << (tree.search(15) ? "Found" : "Not
Found") << endl;
return 0;
}

Q7 Write a program to implement a 2-4 Trees, which supports the following


operations:
a. Insert
b. Search
c. Deletion
Click here to run the code
#include <iostream>
#include <vector>
using namespace std;
void computeLPSArray(string pattern, vector<int> &lps) {
int length = 0;
lps[0] = 0;
int i = 1;
while (i < pattern.size()) {
if (pattern[i] == pattern[length]) {
length++;
lps[i] = length;
i++;
} else {
if (length != 0) {
length = lps[length - 1];
} else {
lps[i] = 0;
i++;
}
}
}
}
void KMPSearch(string text, string pattern) {
int m = pattern.size();
int n = text.size();
vector<int> lps(m);
computeLPSArray(pattern, lps);
int i = 0, j = 0;
while (i < n) {
if (pattern[j] == text[i]) {
i++;
j++;
}
if (j == m) {
cout << "Pattern found at index " << i - j << endl;
j = lps[j - 1];
} else if (i < n && pattern[j] != text[i]) {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
}
int main() {
string text = "ABABDABACDABABCABAB";
string pattern = "ABABCABAB";
KMPSearch(text, pattern);
return 0;
}

Q8 Write a program to search a pattern in a given text using the KMP


algorithm.
Click here to run the code
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
using namespace std;
class SuffixTree {
public:
struct Node {
unordered_map<char, Node*> children;
int start, *end, suffixLink;
Node(int start, int* end) : start(start), end(end), suffixLink(-1) {}
};
string text;
Node* root;
int size;
SuffixTree(string text) {
this->text = text;
this->size = text.size();
root = new Node(-1, new int(-1));
buildTree();
}
void buildTree() {
vector<int> suffixes(size);
int* end = new int(-1);
for (int i = 0; i < size; i++) {
int start = i;
Node* currentNode = root;
while (start < size) {
char currentChar = text[start];
if (currentNode->children.find(currentChar) ==
currentNode->children.end()) {
currentNode->children[currentChar] = new Node(start, end);
break;
}
start++;
currentNode = currentNode->children[currentChar];
}
}
}
void printTree(Node* node, string prefix = "") {
if (node == nullptr) return;
for (auto& child : node->children) {
string currentPrefix = prefix + text.substr(child.second->start,
*child.second->end);
cout << currentPrefix << endl;
printTree(child.second, currentPrefix);
}
}
};
int main() {
string text = "banana";
SuffixTree suffixTree(text);
suffixTree.printTree(suffixTree.root);
return 0;
}

Q9 Write a program to implement a Suffix tree.


Click here to run the code
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;
class SkipListNode {
public:
int value;
vector<SkipListNode*> forward;
SkipListNode(int value, int level) : value(value), forward(level, nullptr) {}
};
class SkipList {
public:
SkipListNode* header;
int maxLevel;
int level;
SkipList(int maxLevel) {
this->maxLevel = maxLevel;
level = 0;
header = new SkipListNode(-1, maxLevel);
}
int randomLevel() {
int lvl = 1;
while (rand() % 2 && lvl < maxLevel) lvl++;
return lvl;
}
void insert(int value) {
vector<SkipListNode*> update(maxLevel, nullptr);
SkipListNode* current = header;
for (int i = level - 1; i >= 0; i--) {
while (current->forward[i] != nullptr && current->forward[i]->value < value)
current = current->forward[i];
update[i] = current;
}
current = current->forward[0];
if (current == nullptr || current->value != value) {
int newLevel = randomLevel();
if (newLevel > level) {
for (int i = level; i < newLevel; i++) update[i] = header;
level = newLevel;
}
current = new SkipListNode(value, newLevel);
for (int i = 0; i < newLevel; i++) {
current->forward[i] = update[i]->forward[i];
update[i]->forward[i] = current;
}
}
}
bool search(int value) {
SkipListNode* current = header;
for (int i = level - 1; i >= 0; i--) {
while (current->forward[i] != nullptr && current->forward[i]->value < value)
current = current->forward[i];
}
current = current->forward[0];
return current != nullptr && current->value == value;
}
void remove(int value) {
vector<SkipListNode*> update(maxLevel, nullptr);
SkipListNode* current = header;
for (int i = level - 1; i >= 0; i--) {
while (current->forward[i] != nullptr && current->forward[i]->value < value)
current = current->forward[i];
update[i] = current;
}
current = current->forward[0];
if (current != nullptr && current->value == value) {
for (int i = 0; i < level; i++) {
if (update[i]->forward[i] != current) break;
update[i]->forward[i] = current->forward[i];
}
delete current;
while (level > 1 && header->forward[level - 1] == nullptr) level--;
}
}
void printList() {
for (int i = 0; i < level; i++) {
SkipListNode* current = header->forward[i];
cout << "Level " << i << ": ";
while (current != nullptr) {
cout << current->value << " ";
current = current->forward[i];
}
cout << endl;
}
}
};
int main() {
srand(time(0));
SkipList list(5);
list.insert(3);
list.insert(6);
list.insert(7);
list.insert(9);
list.insert(12);
list.insert(19);
list.search(6) ? cout << "Found 6" << endl : cout << "Not Found 6" << endl;
list.remove(6);
list.search(6) ? cout << "Found 6" << endl : cout << "Not Found 6" << endl;
list.printList();
return 0;
}

Q10 Write a program to implement Skip lists


Click here to run the code
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
class Graph {
public:
int V;
vector<vector<int>> capacity;
vector<vector<int>> adj;
Graph(int V) {
this->V = V;
capacity.resize(V, vector<int>(V, 0));
adj.resize(V);
}
void addEdge(int u, int v, int cap) {
capacity[u][v] = cap;
adj[u].push_back(v);
adj[v].push_back(u);
}
bool bfs(int s, int t, vector<int>& parent) {
vector<bool> visited(V, false);
queue<int> q;
q.push(s);
visited[s] = true;
parent[s] = -1;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v : adj[u]) {
if (!visited[v] && capacity[u][v] > 0) {
q.push(v);
visited[v] = true;
parent[v] = u;
if (v == t) return true;
}
}
}
return false;
}
int fordFulkerson(int source, int sink) {
int maxFlow = 0;
vector<int> parent(V);
while (bfs(source, sink, parent)) {
int pathFlow = INT_MAX;
for (int v = sink; v != source; v = parent[v]) {
int u = parent[v];
pathFlow = min(pathFlow, capacity[u][v]);
}
maxFlow += pathFlow;
for (int v = sink; v != source; v = parent[v]) {
int u = parent[v];
capacity[u][v] -= pathFlow;
capacity[v][u] += pathFlow;
}
}
return maxFlow;
}
};
int main() {
Graph g(6);
g.addEdge(0, 1, 16);
g.addEdge(0, 2, 13);
g.addEdge(1, 2, 10);
g.addEdge(1, 3, 12);
g.addEdge(2, 1, 4);
g.addEdge(2, 4, 14);
g.addEdge(3, 2, 9);
g.addEdge(3, 5, 20);
g.addEdge(4, 3, 7);
g.addEdge(4, 5, 4);
cout << "Max Flow: " << g.fordFulkerson(0, 5) << endl;
return 0;
}
Q11 Write a program to implement Ford Fulkerson algorithm for the max flow
problem.
Click here to run the code
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class DisjointSet {
public:
vector<int> parent, rank;
DisjointSet(int n) {
parent.resize(n);
rank.resize(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 unionSets(int x, int y) {
int rootX = find(x), rootY = find(y);
if (rootX != rootY) {
if (rank[rootX] > rank[rootY]) parent[rootY] = rootX;
else if (rank[rootX] < rank[rootY]) parent[rootX] = rootY;
else {
parent[rootY] = rootX;
rank[rootX]++;
}
}
}
};
struct Edge {
int u, v, weight;
Edge(int u, int v, int weight) : u(u), v(v), weight(weight) {}
bool operator<(const Edge& other) const {
return weight < other.weight;
}
};
class Graph {
public:
int V;
vector<Edge> edges;
Graph(int V) : V(V) {}

void addEdge(int u, int v, int weight) {


edges.push_back(Edge(u, v, weight));
}

int kruskal() {
sort(edges.begin(), edges.end());
DisjointSet ds(V);
int mstWeight = 0;
for (const Edge& edge : edges) {
int u = edge.u, v = edge.v;
if (ds.find(u) != ds.find(v)) {
ds.unionSets(u, v);
mstWeight += edge.weight;
}
}
return mstWeight;
}
};
int main() {
Graph g(4);
g.addEdge(0, 1, 10);
g.addEdge(0, 2, 6);
g.addEdge(0, 3, 5);
g.addEdge(1, 3, 15);
g.addEdge(2, 3, 4);
cout << "Minimum Spanning Tree Weight: " << g.kruskal() << endl;
return 0;
}

Q12 Write a program to implement Kruskal’s algorithm using Union Find Data
Structure.
Click here to run the code
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

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

class UnionFind {
public:
UnionFind(int size) {
parent.resize(size);
rank.resize(size, 0);
for (int i = 0; i < size; ++i) {
parent[i] = i;
}
}

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

void unionSets(int u, int v) {


int root_u = find(u);
int root_v = find(v);

if (root_u != root_v) {

if (rank[root_u] > rank[root_v]) {


parent[root_v] = root_u;
} else if (rank[root_u] < rank[root_v]) {
parent[root_u] = root_v;
} else {
parent[root_v] = root_u;
rank[root_u]++;
}
}
}

private:
vector<int> parent;
vector<int> rank;
};

class Graph {
public:
Graph(int vertices) : V(vertices) {}

void addEdge(int u, int v, int weight) {


edges.push_back({u, v, weight});
}

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

UnionFind uf(V);
vector<Edge> mst;
int totalWeight = 0;

for (const auto &edge : edges) {


if (uf.find(edge.u) != uf.find(edge.v)) {
uf.unionSets(edge.u, edge.v);
mst.push_back(edge);
totalWeight += edge.weight;
}
}

cout << "Edges in the Minimum Spanning Tree:\n";


for (const auto &edge : mst) {
cout << edge.u << " -- " << edge.v << " == " << edge.weight << endl;
}
cout << "Total weight of MST: " << totalWeight << endl;
}

private:
int V;
vector<Edge> edges;
};

int main() {
Graph g(4);
g.addEdge(0, 1, 10);
g.addEdge(0, 2, 6);
g.addEdge(0, 3, 5);
g.addEdge(1, 3, 15);
g.addEdge(2, 3, 4);

g.kruskal();

return 0;
}

You might also like