Advanced Data Structures Practical Guide
Advanced Data Structures Practical Guide
on
Advanced Data Structure and Algorithms
(M24-CSE-105)
1
INDEX
[Link]. Program Page Remarks
No.
1. Implement an AVL tree. Insert the 5-10
following sequence of numbers: 20, 4,
15, 70, 50. Show the tree structure after
insertion and perform necessary
rotations.
2. Develop a Splay tree and insert the 11-16
following sequence of numbers: 5, 9, 3,
1, 7. Show the tree structure after each
insertion and splay operation.
3. Create a B-tree of order 3 and insert the 17-22
following sequence of numbers: 10, 20,
5, 6, 12. Show the tree structure after
each insertion.
4. Construct a Red-Black tree and insert 23-29
the following sequence of numbers: 10,
18, 7, 15, 16. Show the tree structure
after each insertion and color
adjustment.
5. Implement a Binomial heap and 30-35
perform the following operations:
insert(10), insert(20), insert(5). Show
the heap structure after each insertion.
6. Develop a Fibonacci heap and perform 36-40
the following operations: insert(10),
insert(20), insert(5). Show the heap
structure after each insertion.
7. Create a Pairing heap and perform the 41-44
following operations: insert(10),
insert(20), insert(5). Show the heap
structure after each insertion.
8. Perform traversal of graph DFS. 45-47
9. Perform traversal of graph BFS. 48-49
2
10. Create an algorithm for topological 50-52
sorting and apply it to a directed acyclic
graph (DAG) with 10 vertices and 12
edges.
11. Implement Tarjan's algorithm to find 53-56
strongly connected components (SCCs)
in a directed graph with 10 vertices and
15 edges.
12. Implement the buddy system for 57-60
memory allocation. Simulate the
allocation and deallocation of memory
blocks of sizes 64KB, 128KB, 32KB,
and 256KB, and show the memory
structure after each operation.
13. Develop a memory pool allocation 61-63
system for fixed-size memory blocks of
64 bytes. Simulate the allocation and
deallocation of 1,000 blocks and
measure the time taken for these
operations.
14. Compare different garbage collection 64-68
algorithms (mark-and-sweep, reference
counting, generational) by simulating a
program that creates and destroys
objects, and measure the memory usage
and time taken.
15. Implement a basic mark-and-sweep 69-72
garbage collector in a simulated
environment with 100 objects and show
the effect on memory usage after
garbage collection.
16. Analyze the trade-offs between different 73-79
memory allocation strategies (e.g.,
buddy system vs. memory pool) by
simulating memory usage patterns and
measuring performance.
17. Implement Dijkstra's algorithm to find 80-82
3
the shortest path in a weighted graph
with 10 vertices and 20 edges, and
analyze its time complexity.
18. Develop Bellman-Ford algorithm to 83-85
handle graphs with negative weight
edges and demonstrate its use in
detecting negative cycles in a graph
with 10 vertices and 15 edges.
19. Create Floyd-Warshall algorithm for 86-90
finding all pairs shortest paths in a
graph with 5 vertices and 10 edges, and
compare its performance with Dijkstra's
algorithm.
20. Implement Kruskal's algorithm to 91-94
find the minimum spanning tree of
a graph with 10 vertices and 15
edges, and analyze its efficiency.
21. Develop Prim's algorithm for minimum 95-101
spanning trees and compare its
performance with Kruskal's algorithm
on a graph with 10 vertices and 15
edges.
5
y->left = T2;
y->height = max(height(y->left), height(y->right)) + 1;
x->height = max(height(x->left), height(x->right)) + 1;
return x;
}
struct Node* leftRotate(struct Node* x) {
struct Node* y = x->right;
struct Node* T2 = y->left;
y->left = x;
x->right = T2;
x->height = max(height(x->left), height(x->right)) + 1;
y->height = max(height(y->left), height(y->right)) + 1;
return y;
}
int getBalance(struct Node* n) {
if (n == NULL)
return 0;
return height(n->left) - height(n->right);
}
struct Node* insert(struct Node* node, int key) {
if (node == NULL)
return newNode(key);
if (key < node->key)
node->left = insert(node->left, key);
6
else if (key > node->key)
node->right = insert(node->right, key);
else
return node;
node->height = 1 + max(height(node->left), height(node->right));
int balance = getBalance(node);
if (balance > 1 && key < node->left->key)
return rightRotate(node);
if (balance < -1 && key > node->right->key)
return leftRotate(node);
if (balance > 1 && key > node->left->key) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
if (balance < -1 && key < node->right->key) { // RL
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
void printTree(struct Node* root, int space) {
if (root == NULL)
return;
space += 5;
7
printTree(root->right, space);
printf("\n");
for (int i = 5; i < space; i++)
printf(" ");
printf("%d\n", root->key);
printTree(root->left, space);
}
int main() {
struct Node* root = NULL;
int arr[] = {20, 4, 15, 70, 50};
int n = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < n; i++) {
printf("\nInserting %d...\n", arr[i]);
root = insert(root, arr[i]);
printTree(root, 0);
}
return 0;
}
Output:
Inserting 20...
8
20
Inserting 4...
20
Inserting 15...
20
15
Inserting 70...
70
9
20
15
Inserting 50...
70
50
20
15
4
2. Develop a Splay tree and insert the following sequence of
numbers: 5, 9, 3, 1, 7. Show the tree structure after each
insertion and splay operation
#include <stdio.h>
#include <stdlib.h>
10
struct Node {
int key;
struct Node *left, *right;
};
struct Node* newNode(int key) {
struct Node* node = (struct Node*)malloc(sizeof(struct Node));
node->key = key;
node->left = node->right = NULL;
return node;
}
struct Node* rightRotate(struct Node* x) {
struct Node* y = x->left;
x->left = y->right;
y->right = x;
return y;
}
struct Node* leftRotate(struct Node* x) {
struct Node* y = x->right;
x->right = y->left;
y->left = x;
return y;
}
struct Node* splay(struct Node* root, int key) {
if (root == NULL || root->key == key)
11
return root;
if (key < root->key) {
if (root->left == NULL)
return root;
if (key < root->left->key) {
root->left->left = splay(root->left->left, key);
root = rightRotate(root);
} else if (key > root->left->key) {
root->left->right = splay(root->left->right, key);
if (root->left->right)
root->left = leftRotate(root->left);
}
return (root->left == NULL) ? root
rightRotate(root);
}
else {
if (root->right == NULL) return root;
if (key > root->right->key) {
root->right->right = splay(root->right->right, key);
root = leftRotate(root);
} else if (key < root->right->key) {
root->right->left = splay(root->right->left, key);
if (root->right->left)
root->right = rightRotate(root->right);
12
}
return (root->right == NULL) ? root : leftRotate(root);
}
}
struct Node* insert(struct Node* root, int key) {
if (root == NULL)
return newNode(key);
root = splay(root, key);
if (root->key == key)
return root;
struct Node* node = newNode(key);
if (key < root->key) {
node->right = root;
node->left = root->left;
root->left = NULL;
} else {
node->left = root;
node->right = root->right;
root->right = NULL;
}
return node;
}
void printTree(struct Node* root, int space) {
if (!root) return;
13
space += 5;
printTree(root->right, space);
printf("\n");
for (int i = 5; i < space; i++) printf(" ");
printf("%d\n", root->key);
printTree(root->left, space);
}
int main() {
struct Node* root = NULL;
int arr[] = {5, 9, 1, 7};
int n = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < n; i++) {
printf("\nInsert %d:\n", arr[i]);
root = insert(root, arr[i]);
printTree(root, 0);
}
return 0;
}
Output:
Insert 5:
5
14
Insert 9:
Insert 1:
Insert 7:
15
5
16
int keys[ORDER];
struct BTreeNode *child[ORDER + 1];
int n;
int leaf;
} BTreeNode;
BTreeNode *root = NULL;
BTreeNode *createNode(int leaf) {
BTreeNode *node = (BTreeNode *)malloc(sizeof(BTreeNode));
node->leaf = leaf;
node->n = 0;
for (int i = 0; i <= ORDER; i++)
node->child[i] = NULL;
return node;
}
void printTree(BTreeNode *node, int level) {
if (node == NULL) return;
printf("\nLevel %d [", level);
for (int i = 0; i < node->n; i++)
printf(" %d ", node->keys[i]);
printf("]");
for (int i = 0; i <= node->n; i++)
if (node->child[i])
printTree(node->child[i], level + 1);
}
17
void splitChild(BTreeNode *parent, int i, BTreeNode *fullChild) {
int t = ORDER / 2;
BTreeNode *newChild = createNode(fullChild->leaf);
newChild->n = t;
for (int j = 0; j < t; j++)
newChild->keys[j] = fullChild->keys[j + t + 1];
if (!fullChild->leaf) {
for (int j = 0; j <= t; j++)
newChild->child[j] = fullChild->child[j + t + 1];
}
fullChild->n = t;
for (int j = parent->n; j >= i + 1; j--)
parent->child[j + 1] = parent->child[j];
parent->child[i + 1] = newChild;
for (int j = parent->n - 1; j >= i; j--)
parent->keys[j + 1] = parent->keys[j];
parent->keys[i] = fullChild->keys[t];
parent->n++;
}
void insertNonFull(BTreeNode *node, int k) {
int i = node->n - 1;
if (node->leaf) {
while (i >= 0 && k < node->keys[i]) {
node->keys[i + 1] = node->keys[i];
18
i--;
}
node->keys[i + 1] = k;
node->n++;
} else {
while (i >= 0 && k < node->keys[i])
i--;
i++;
if (node->child[i]->n == ORDER) {
splitChild(node, i, node->child[i]);
if (k > node->keys[i])
i++;
}
insertNonFull(node->child[i], k);
}
}
void insert(int k) {
if (root == NULL) {
root = createNode(1);
root->keys[0] = k;
root->n = 1;
} else {
if (root->n == ORDER) {
BTreeNode *newRoot = createNode(0);
19
newRoot->child[0] = root;
splitChild(newRoot, 0, root);
int i = 0;
if (k > newRoot->keys[0])
i++;
insertNonFull(newRoot->child[i], k);
root = newRoot;
} else {
insertNonFull(root, k);
}
}
}
int main() {
int arr[] = {10, 20, 5, 6, 12};
int n = sizeof(arr) / sizeof(arr[0]);
printf("B-Tree of order 3 insertion:\n");
for (int i = 0; i < n; i++) {
printf("\n\nAfter inserting %d:", arr[i]);
insert(arr[i]);
printTree(root, 0);
printf("\n");
}
return 0;
}
20
Output:
B-Tree of order 3 insertion:
After inserting 10:
Level 0 [ 10 ]
21
After inserting 5:
Level 0 [ 5 10 20 ]
After inserting 6:
Level 0 [ 10 ]
Level 1 [ 5 6 ]
Level 1 [ 20]
22
struct Node *left, *right, *parent;
};
struct Node* createNode(int data) {
struct Node* n = (struct Node*)malloc(sizeof(struct Node));
n->data = data;
n->color = RED;
n->left = n->right = n->parent = NULL;
return n;
}
struct Node* rotateLeft(struct Node* root, struct Node* x) {
struct Node* y = x->right;
x->right = y->left;
if (y->left) y->left->parent = x;
y->parent = x->parent;
if (!x->parent) root = y;
else if (x == x->parent->left) x->parent->left = y;
else x->parent->right = y;
y->left = x;
x->parent = y;
return root;
}
struct Node* rotateRight(struct Node* root, struct Node* y) {
struct Node* x = y->left;
y->left = x->right;
23
if (x->right) x->right->parent = y;
x->parent = y->parent;
if (!y->parent) root = x;
else if (y == y->parent->left) y->parent->left = x;
else y->parent->right = x;
x->right = y;
y->parent = x;
return root;
}
24
}
z->parent->color = BLACK; // Case 3
gp->color = RED;
25
root->color = BLACK;
return root;
}
struct Node* insert(struct Node* root, int data) {
struct Node* z = createNode(data);
struct Node* y = NULL;
struct Node* x = root;
while (x != NULL) {
y = x;
if (z->data < x->data) x = x->left;
else x = x->right;
}
z->parent = y;
if (y == NULL) root = z;
else if (z->data < y->data) y->left = z;
else y->right = z;
return fixInsert(root, z);
}
void printTree(struct Node* root, int space) {
if (!root) return;
space += 8;
printTree(root->right, space);
printf("\n");
for (int i = 8; i < space; i++) printf(" ");
26
printf("%d(%c)\n", root->data, root->color == RED ? 'R' : 'B');
printTree(root->left, space);
}
int main() {
struct Node* root = NULL;
int arr[] = {10, 18, 7, 15, 16};
int n = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < n; i++) {
printf("\nInsert %d:\n", arr[i]);
root = insert(root, arr[i]);
printTree(root, 0);
}
return 0;
}
Output:
Insert 10:
10(B)
Insert 18:
18(R)
27
10(B)
Insert 7:
18(R)
10(B)
7(R)
Insert 15:
18(B)
15(R)
10(B)
7(B)
28
Insert 16:
18(R)
16(B)
15(R)
10(B)
7(B)
29
struct BinomialNode *sibling;
} BinomialNode;
BinomialNode* createNode(int key) {
BinomialNode* newNode =
(BinomialNode*)malloc(sizeof(BinomialNode));
newNode->key = key;
newNode->degree = 0;
newNode->parent = NULL;
newNode->child = NULL;
newNode->sibling = NULL;
return newNode;
}
void binomialLink(BinomialNode* y, BinomialNode* z) {
y->parent = z;
y->sibling = z->child;
z->child = y;
z->degree++;
}
BinomialNode* binomialMerge(BinomialNode* h1, BinomialNode*
h2) {
if (!h1) return h2;
if (!h2) return h1;
BinomialNode* head;
BinomialNode* tail;
30
if (h1->degree <= h2->degree) {
head = h1;
h1 = h1->sibling;
} else {
head = h2;
h2 = h2->sibling;
}
tail = head;
while (h1 && h2) {
if (h1->degree <= h2->degree) {
tail->sibling = h1;
h1 = h1->sibling;
} else {
tail->sibling = h2;
h2 = h2->sibling;
}
tail = tail->sibling;
}
tail->sibling = h1 ? h1 : h2;
return head;
}
BinomialNode* binomialUnion(BinomialNode* h1, BinomialNode*
h2) {
BinomialNode* newHeap = binomialMerge(h1, h2);
31
if (!newHeap) return NULL;
BinomialNode* prev = NULL;
BinomialNode* curr = newHeap;
BinomialNode* next = curr->sibling;
while (next != NULL) {
if ((curr->degree != next->degree) ||
(next->sibling != NULL && next->sibling->degree == curr-
>degree)) {
prev = curr;
curr = next;
} else {
if (curr->key <= next->key) {
curr->sibling = next->sibling;
binomialLink(next, curr);
} else {
if (prev == NULL)
newHeap = next;
else
prev->sibling = next;
binomialLink(curr, next);
curr = next;
}
}
next = curr->sibling;
32
}
return newHeap;
}
BinomialNode* insert(BinomialNode* heap, int key) {
BinomialNode* newNode = createNode(key);
heap = binomialUnion(heap, newNode);
return heap;
}
void displayHeap(BinomialNode* h){
printf("\nBinomial Heap Structure:\n");
BinomialNode* temp = h;
while (temp != NULL) {
printf("B%d: ", temp->degree);
printf("(root %d) ", temp->key);
if (temp->child) {
BinomialNode* c = temp->child;
printf("[children: ");
while (c) {
printf("%d ", c->key);
c = c->sibling;
}
printf("]");
}
printf("\n");
33
temp = temp->sibling;
}
}
int main() {
BinomialNode* heap = NULL;
printf("Inserting 10...\n");
heap = insert(heap, 10);
displayHeap(heap);
printf("Inserting 20...\n");
heap = insert(heap, 20);
displayHeap(heap);
printf("Inserting 5...\n");
heap = insert(heap, 5);
displayHeap(heap);
return 0;
}
Output:
Inserting 10...
Binomial Heap Structure:
B0: (root 10)
Inserting 20...
Binomial Heap Structure:
34
B1: (root 10) [children: 20 ]
Inserting 5...
Binomial Heap Structure:
B0: (root 5)
B1: (root 10) [children: 20 ]
35
struct FibonacciNode *right;
int mark;
} FibonacciNode;
typedef struct FibonacciHeap {
FibonacciNode *min;
int n;
} FibonacciHeap;
FibonacciNode* createNode(int key) {
FibonacciNode* node =
(FibonacciNode*)malloc(sizeof(FibonacciNode));
node->key = key;
node->degree = 0;
node->parent = NULL;
node->child = NULL;
node->left = node;
node->right = node;
node->mark = 0;
return node;
}
FibonacciHeap* createHeap() {
FibonacciHeap* heap =
(FibonacciHeap*)malloc(sizeof(FibonacciHeap));
heap->min = NULL;
heap->n = 0;
36
return heap;
}
void insertNode(FibonacciHeap* heap, FibonacciNode* node) {
if (heap->min == NULL) {
heap->min = node;
} else {
node->left = heap->min;
node->right = heap->min->right;
heap->min->right->left = node;
heap->min->right = node;
if (node->key < heap->min->key)
heap->min = node;
}
heap->n++;
}
void insert(FibonacciHeap* heap, int key) {
FibonacciNode* node = createNode(key);
insertNode(heap, node);
printf("Inserted %d into Fibonacci Heap.\n", key);
}
void displayHeap(FibonacciHeap* heap) {
if (heap->min == NULL) {
printf("\nFibonacci Heap is empty.\n");
return;
37
}
printf("\nFibonacci Heap Structure:\n");
FibonacciNode* temp = heap->min;
FibonacciNode* start = temp;
do {
printf("Key: %d (degree %d)\n", temp->key, temp->degree);
if (temp->child) {
printf(" Children: ");
FibonacciNode* c = temp->child;
FibonacciNode* cstart = c;
do {
printf("%d ", c->key);
c = c->right;
} while (c != cstart);
printf("\n");
}
temp = temp->right;
} while (temp != start);
}
int main() {
FibonacciHeap* heap = createHeap();
insert(heap, 10);
displayHeap(heap);
insert(heap, 20);
38
displayHeap(heap);
insert(heap, 5);
displayHeap(heap);
return 0;
}
Output:
Inserted 10 into Fibonacci Heap.
Fibonacci Heap Structure:
Key: 10 (degree 0)
39
Inserted 5 into Fibonacci Heap.
Fibonacci Heap Structure:
Key: 5 (degree 0)
Key: 20 (degree 0)
Key: 10 (degree 0)
40
node->key = key;
node->child = NULL;
node->sibling = NULL;
return node;
}
PairNode* merge(PairNode* h1, PairNode* h2) {
if (h1 == NULL)
return h2;
if (h2 == NULL)
return h1;
41
heap = merge(heap, newNode);
printf("Inserted %d into Pairing Heap.\n", key);
return heap;
}
void displayHeap(PairNode* root, int level) {
if (root == NULL)
return;
for (int i = 0; i < level; i++)
printf(" ");
printf("%d\n", root->key);
displayHeap(root->child, level + 1);
displayHeap(root->sibling, level);
}
void showHeap(PairNode* heap) {
printf("\nPairing Heap Structure:\n");
displayHeap(heap, 0);
}
int main() {
PairNode* heap = NULL;
heap = insert(heap, 10);
showHeap(heap);
heap = insert(heap, 20);
showHeap(heap);
heap = insert(heap, 5);
42
showHeap(heap);
return 0;
}
Output:
Inserted 10 into Pairing Heap.
Pairing Heap Structure:
10
43
5
10
20
44
struct Node* newNode = (struct Node*)malloc(sizeof(struct
Node));
newNode->dest = dest;
newNode->next = NULL;
return newNode;
}
void DFSRec(struct AdjList adj[], int visited[], int s) {
visited[s] = 1;
printf("%d ", s);
struct Node* current = adj[s].head;
while (current != NULL) {
int dest = current->dest;
if (!visited[dest]) {
DFSRec(adj, visited, dest);
}
current = current->next;
}
}
void DFS(struct AdjList adj[], int V, int s) {
int visited[V];
for (int i = 0; i < V; i++)
visited[i] = 0;
45
}
void addEdge(struct AdjList adj[], int s, int t) {
struct Node* newNode = createNode(t);
newNode->next = adj[s].head;
adj[s].head = newNode;
newNode = createNode(s);
newNode->next = adj[t].head;
adj[t].head = newNode;
}
int main() {
int V = 5;
struct AdjList adj[V];
for (int i = 0; i < V; i++) {
adj[i].head = NULL;
}
int E = 5;
int edges[][2] = {{1, 2}, {1, 0}, {2, 0}, {2, 3}, {2, 4}};
for (int i = 0; i < E; i++) {
addEdge(adj, edges[i][0], edges[i][1]);
}
int source = 1;
printf("DFS from source %d:\n", source);
DFS(adj, V, source);
return 0;
46
}
Output:
DFS from source 1:
10243
47
int curr = q[front++];
printf("%d ", curr);
for (int i = 0; i < V; i++) {
if (adj[curr][i] == 1 && !visited[i]) {
visited[i] = true;
q[rear++] = i;
}
}
}
}
void addEdge(int adj[MAX][MAX], int u, int v) {
adj[u][v] = 1;
adj[v][u] = 1;
}
int main() {
int V = 5;
int adj[MAX][MAX] = {0};
addEdge(adj, 0, 1);
addEdge(adj, 0, 2);
addEdge(adj, 1, 3);
addEdge(adj, 1, 4);
addEdge(adj, 2, 4);
printf("BFS starting from 0:\n");
BFS(adj, V, 0);
48
return 0;
}
Output:
BFS starting from 0:
01234
50
if (indegree[temp->vertex] == 0)
queue[rear++] = temp->vertex;
temp = temp->next;
}
}
if (k != V) {
printf("Graph has a cycle! Topological sort not possible.\n");
return;
}
printf("Topological Sort Order: ");
for (int i = 0; i < V; i++)
printf("%d ", topoOrder[i]);
printf("\n");
}
int main() {
for (int i = 0; i < V; i++) {
adjList[i] = NULL;
indegree[i] = 0;
}
int edges[E][2] = {
{0, 2}, {0, 3},
{1, 3}, {1, 4},
{2, 5}, {3, 5},
{3, 6}, {4, 6},
51
{5, 7}, {6, 8},
{7, 9}, {8, 9}
};
for (int i = 0; i < E; i++)
addEdge(edges[i][0], edges[i][1]);
topologicalSort();
return 0;
}
Output:
Topological Sort Order:
0124365879
11. Implement Tarjan's algorithm to find strongly connected
components (SCCs) in a directed graph with 10 vertices and 15
edges
#include <stdio.h>
#include <stdlib.h>
#define V 10
#define E 15
int adj[V][V];
int indexCounter = 0;
int indices[V], lowlink[V], onStack[V];
int stack[V], top = -1;
void push(int v) { stack[++top] = v; }
52
int pop() { return stack[top--]; }
void addEdge(int u, int v) {
adj[u][v] = 1;
}
void tarjanDFS(int u) {
indices[u] = lowlink[u] = indexCounter++;
push(u);
onStack[u] = 1;
for (int v = 0; v < V; v++) {
if (adj[u][v]) {
if (indices[v] == -1) {
tarjanDFS(v);
lowlink[u] = (lowlink[u] < lowlink[v]) ? lowlink[u] :
lowlink[v];
}
else if (onStack[v]) {
lowlink[u] = (lowlink[u] < indices[v]) ? lowlink[u] :
indices[v];
}
}
}
if (lowlink[u] == indices[u]) {
printf("SCC: ");
while (1) {
53
int v = pop();
onStack[v] = 0;
printf("%d ", v);
if (v == u) break;
}
printf("\n");
}
}
int main() {
for (int i = 0; i < V; i++)
for (int j = 0; j < V; j++)
adj[i][j] = 0;
int edges[15][2] = {
{0,1},{1,2},{2,0},
{3,4},{4,5},{5,3},
{6,7},{7,8},{8,6},
{2,3},{5,6},{8,9},
{1,9},{4,7},{0,5}
};
top = -1;
indexCounter = 0;
for (int i = 0; i < V; i++) {
indices[i] = -1;
lowlink[i] = 0;
54
onStack[i] = 0;
}
for (int i = 0; i < 15; i++)
addEdge(edges[i][0], edges[i][1]);
printf("Strongly Connected Components:\n");
for (int i = 0; i < V; i++)
if (indices[i] == -1)
tarjanDFS(i);
return 0;
}
Output:
Strongly Connected Components:
SCC: 9
SCC: 8 7 6
SCC: 5 4 3
SCC: 2 1 0
55
12. Implement the buddy system for memory allocation. Simulate
the allocation and deallocation of memory blocks of sizes
64KB, 128KB, 32KB, and 256KB, and show the memory
structure after each operation
#include <stdio.h>
#include <math.h>
#include <string.h>
#define MAX 1024
#define LEVELS 10
int memory[MAX];
int buddyFree[LEVELS];
void printMemory() {
printf("Memory Blocks (0 = Free, 1 = Used):\n");
for (int i = 0; i < 64; i++)
56
printf("%d", memory[i]);
printf("\n\n");
}
int nextPower(int size) {
int p = 1;
while (p < size) p *= 2;
return p;
}
void allocate(int size) {
int block = nextPower(size);
int idx = -1;
for (int i = 0; i < MAX; i += block) {
int free = 1;
for (int j = i; j < i + block; j++) {
if (memory[j] == 1) {
free = 0;
break;
}
}
if (free) {
idx = i;
break;
}
}
57
if (idx == -1) {
printf("Cannot allocate %d KB\n", size);
return;
}
for (int i = idx; i < idx + block; i++)
memory[i] = 1;
printf("Allocated %d KB (block %d KB) at index %d\n", size,
block, idx);
printMemory();
}
void deallocate(int size, int start) {
int block = nextPower(size);
for (int i = start; i < start + block; i++)
memory[i] = 0;
printf("Deallocated %d KB (block %d KB) from index %d\n", size,
block, start);
printMemory();
}
int main() {
memset(memory, 0, sizeof(memory));
allocate(64);
allocate(128);
allocate(32);
allocate(256);
58
deallocate(128, 64);
return 0;
}
Output:
Allocated 64 KB (block 64 KB) at index 0
Memory Blocks (0 = Free, 1 = Used):
111111111111111111111111111111111111111111111111111111111111
1111
Allocated 128 KB (block 128 KB) at index 128
Memory Blocks (0 = Free, 1 = Used):
111111111111111111111111111111111111111111111111111111111111
1111
Allocated 32 KB (block 32 KB) at index 32
Memory Blocks (0 = Free, 1 = Used):
111111111111111111111111111111111111111111111111111111111111
1111
Allocated 256 KB (block 256 KB) at index 256
59
Memory Blocks (0 = Free, 1 = Used):
111111111111111111111111111111111111111111111111111111111111
1111
Deallocated 128 KB (block 128 KB) from index 64Memory Blocks (0
= Free, 1 =
Used)1111111111111111111111111111111111111111111111111111111
11111111111
61
start = clock();
for (int i = 0; i < NUM_BLOCKS; i++) {
allocated[i] = allocateBlock();
if (!allocated[i]) {
printf("Memory pool exhausted at block %d\n", i);
break;
}
}
end = clock();
allocTime = ((double)(end - start)) / CLOCKS_PER_SEC;
start = clock();
for (int i = 0; i < NUM_BLOCKS; i++) {
deallocateBlock(allocated[i]);
}
end = clock();
deallocTime = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("Allocated %d blocks of %d bytes\n", NUM_BLOCKS,
BLOCK_SIZE);
printf("Allocation time: %.6f seconds\n", allocTime);
printf("Deallocation time: %.6f seconds\n", deallocTime);
return 0;
}
Output:
62
Allocated 1000 blocks of 64 bytes
Allocation time: 0.000007 seconds
Deallocation time: 0.000006 seconds
63
Object* heap[NUM_OBJECTS];
Object* roots[1000];
int rootCount = 0;
double now() {
return (double)clock() / CLOCKS_PER_SEC;
}
Object* newObject(int id) {
Object* obj = (Object*)malloc(sizeof(Object));
obj->id = id;
obj->marked = 0;
obj->refCount = 1;
obj->numChildren = 0;
return obj;
}
void addChild(Object* parent, Object* child) {
if (parent->numChildren < MAX_CHILDREN) {
parent->children[parent->numChildren++] = child;
child->refCount++;
}
}
void rcDelete(Object* obj) {
if (!obj || --obj->refCount > 0) return;
64
rcDelete(obj->children[i]);
free(obj);
}
void runReferenceCounting() {
double t = now();
for (int i = 0; i < NUM_OBJECTS; i++) {
heap[i] = newObject(i);
if (i > 0)
addChild(heap[i - 1], heap[i]);
}
for (int i = 0; i < NUM_OBJECTS; i++)
rcDelete(heap[i]);
printf("Reference Counting Time: %.4f sec\n", now() - t);
}
void mark(Object* obj) {
if (!obj || obj->marked) return;
obj->marked = 1;
for (int i = 0; i < obj->numChildren; i++)
mark(obj->children[i]);
}
void sweep() {
for (int i = 0; i < NUM_OBJECTS; i++) {
if (heap[i] && !heap[i]->marked) {
free(heap[i]);
65
heap[i] = NULL;
} else if (heap[i]) {
heap[i]->marked = 0; // reset for next cycle
}
}
}
void runMarkAndSweep() {
double t = now();
for (int i = 0; i < NUM_OBJECTS; i++) {
heap[i] = newObject(i);
if (i > 0)
addChild(heap[i - 1], heap[i]);
}
roots[rootCount++] = heap[0];
for (int i = 0; i < rootCount; i++)
mark(roots[i]);
sweep();
printf("Mark-and-Sweep Time: %.4f sec\n", now() - t);
}
#define YOUNG_SIZE 20000
Object* youngGen[YOUNG_SIZE];
Object* oldGen[NUM_OBJECTS];
66
void promote(Object* obj) {
oldGen[oldCount++] = obj;
}
void runGenerationalGC() {
double t = now();
for (int i = 0; i < NUM_OBJECTS; i++) {
Object* obj = newObject(i);
if (youngCount < YOUNG_SIZE)
youngGen[youngCount++] = obj;
else
promote(obj);
}
for (int i = 0; i < youngCount; i++)
free(youngGen[i]);
youngCount = 0;
for (int i = 0; i < oldCount; i++)
free(oldGen[i]);
printf("Generational GC Time: %.4f sec\n", now() - t);
}
int main() {
printf("Creating objects: %d\n\n", NUM_OBJECTS);
runReferenceCounting();
runMarkAndSweep();
runGenerationalGC();
67
return 0;
}
Output:
Creating objects: 50000
Reference Counting Time: 0.0031 sec
Mark-and-Sweep Time: 0.0031 sec
Generational GC Time: 0.0027 sec
15. Implement a basic mark-and-sweep garbage collector in a
simulated environment with 100 objects and show the effect on
memory usage after garbage collection
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 100
#define MAXREF 3
#define ROOTS 5
typedef struct Object {
int id;
int marked;
int num_refs;
struct Object* refs[MAXREF];
} Object;
Object* heap[N];
Object* roots[ROOTS];
68
Object* createObject(int id) {
Object* obj = (Object*)malloc(sizeof(Object));
obj->id = id;
obj->marked = 0;
obj->num_refs = 0;
for (int i = 0; i < MAXREF; i++)
obj->refs[i] = NULL;
return obj;
}
void mark(Object* obj) {
if (!obj || obj->marked) return;
obj->marked = 1;
for (int i = 0; i < obj->num_refs; i++)
mark(obj->refs[i]);
}
int sweep() {
int freed = 0;
for (int i = 0; i < N; i++) {
if (heap[i] != NULL && heap[i]->marked == 0) {
free(heap[i]);
heap[i] = NULL;
freed++;
}
else if (heap[i] != NULL) {
69
heap[i]->marked = 0; // reset for next cycle
}
}
return freed;
}
void showMemoryUsage() {
int used = 0;
for (int i = 0; i < N; i++)
if (heap[i] != NULL)
used++;
printf("Objects currently alive: %d\n", used);
}
int main() {
srand(time(0));
for (int i = 0; i < N; i++)
heap[i] = createObject(i);
for (int i = 0; i < N; i++) {
int refCount = rand() % (MAXREF + 1);
heap[i]->num_refs = refCount;
70
for (int i = 0; i < ROOTS; i++)
roots[i] = heap[rand() % N];
Output:
=== Memory Usage Before Garbage Collection ===
Objects currently alive: 100
71
16. Analyze the trade-offs between different memory allocation
strategies (e.g., buddy system vs. memory pool) by simulating
memory usage patterns and measuring performance
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TOTAL_MEMORY (1024 * 1024)
#define BLOCK_SIZE 64
#define OPS 50000
unsigned char pool[TOTAL_MEMORY];
int pool_free[(TOTAL_MEMORY / BLOCK_SIZE)];
void pool_init() {
int total_blocks = TOTAL_MEMORY / BLOCK_SIZE;
for (int i = 0; i < total_blocks; i++)
pool_free[i] = 1;
}
void* pool_alloc(int size) {
int needed = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
int total_blocks = TOTAL_MEMORY / BLOCK_SIZE;
72
int count = 0, start = -1;
73
typedef struct Buddy {
int size;
int free;
struct Buddy* next;
} Buddy;
Buddy* buddy_list[20];
74
buddy_list[level_from_size(TOTAL_MEMORY)] = root;
}
Buddy* buddy_alloc(int size) {
int level = level_from_size(size);
int i = level;
while (i < 20 && buddy_list[i] == NULL)
i++;
if (i == 20) return NULL;
Buddy* block = buddy_list[i];
buddy_list[i] = block->next;
while (i > level) {
i--;
Buddy* buddy = (Buddy*)malloc(sizeof(Buddy));
buddy->size = (1 << i);
buddy->free = 1;
buddy->next = buddy_list[i];
buddy_list[i] = buddy;
block->size = (1 << i);
}
block->free = 0;
return block;
}
void buddy_free(Buddy* block) {
int level = level_from_size(block->size);
75
block->free = 1;
block->next = buddy_list[level];
buddy_list[level] = block;
}
int random_size() {
return (rand() % 500) + 1;
}
double time_now() {
return (double)clock() / CLOCKS_PER_SEC;
}
double fragmentation_pool() {
int used = 0, total = TOTAL_MEMORY / BLOCK_SIZE;
for (int i = 0; i < total; i++)
if (!pool_free[i]) used++;
return 100.0 * (1.0 - ((double)used * BLOCK_SIZE) /
TOTAL_MEMORY);
}
double fragmentation_buddy() {
int free_bytes = 0;
for (int i = 0; i < 20; i++) {
Buddy* b = buddy_list[i];
while (b) {
if (b->free) free_bytes += b->size;
b = b->next;
76
}
}
return 100.0 * free_bytes / TOTAL_MEMORY;
}
int main() {
srand(time(NULL));
pool_init();
double t1 = time_now();
for (int i = 0; i < OPS; i++) {
int size = random_size();
void* p = pool_alloc(size);
if (p) pool_free_block(p, size);
}
double t_pool = time_now() - t1;
buddy_init();
t1 = time_now();
for (int i = 0; i < OPS; i++) {
int size = random_size();
Buddy* b = buddy_alloc(size);
if (b) buddy_free(b);
}
double t_buddy = time_now() - t1;
printf("\n===== MEMORY ALLOCATION STRATEGY
COMPARISON =====\n");
77
printf("Buddy System: time = %.4f sec, fragmentation = %.2f%%\
n",
t_buddy, fragmentation_buddy());
printf("Memory Pool: time = %.4f sec, fragmentation = %.2f%%\
n",
t_pool, fragmentation_pool());
return 0;
}
Output:
===== MEMORY ALLOCATION STRATEGY COMPARISON
=====
Buddy System: time = 0.0016 sec, fragmentation = 0.00%
Memory Pool: time = 0.0024 sec, fragmentation = 100.00%
78
17. Implement Dijkstra's algorithm to find the shortest path in a
weighted graph with 10 vertices and 20 edges, and analyze its
time complexity
#include <stdio.h>
#include <limits.h>
#define V 10
int minDistance(int dist[], int visited[]) {
int min = INT_MAX, index = -1;
for (int i = 0; i < V; i++) {
if (!visited[i] && dist[i] < min) {
min = dist[i];
index = i;
}
}
return index;
}
void dijkstra(int graph[V][V], int src) {
int dist[V], visited[V];
for (int i = 0; i < V; i++) {
dist[i] = INT_MAX;
79
visited[i] = 0;
}
dist[src] = 0;
for (int count = 0; count < V - 1; count++) {
int u = minDistance(dist, visited);
visited[u] = 1;
for (int v = 0; v < V; v++) {
if (!visited[v] && graph[u][v] &&
dist[u] != INT_MAX &&
dist[u] + graph[u][v] < dist[v]) {
dist[v] = dist[u] + graph[u][v];
}
}
}
printf("Vertex \tDistance from Source\n");
for (int i = 0; i < V; i++) {
printf("%d \t%d\n", i, dist[i]);
}
}
int main() {
int graph[V][V] = {
{0, 4, 0, 0, 0, 0, 0, 8, 0, 0},
{4, 0, 8, 0, 0, 0, 0, 11, 0, 0},
{0, 8, 0, 7, 0, 4, 0, 0, 2, 0},
80
{0, 0, 7, 0, 9, 14, 0, 0, 0, 0},
{0, 0, 0, 9, 0, 10, 0, 0, 0, 0},
{0, 0, 4, 14, 10, 0, 2, 0, 0, 0},
{0, 0, 0, 0, 0, 2, 0, 1, 6, 0},
{8, 11, 0, 0, 0, 0, 1, 0, 7, 0},
{0, 0, 2, 0, 0, 0, 6, 7, 0, 3},
{0, 0, 0, 0, 0, 0, 0, 0, 3, 0}
};
dijkstra(graph, 0);
return 0;
}
Output:
Vertex Distance from Source
0 0
1 4
2 12
3 19
4 21
5 11
6 9
7 8
8 14
9 17
81
18. Develop Bellman-Ford algorithm to handle graphs with
negative weight edges and demonstrate its use in detecting
negative cycles in a graph with 10 vertices and 15 edges
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define V 10
#define E 15
typedef struct {
int src, dest, weight;
} Edge;
typedef struct {
int numVertices, numEdges;
Edge edges[E];
} Graph;
Graph* createGraph() {
Graph* graph = (Graph*)malloc(sizeof(Graph));
graph->numVertices = V;
graph->numEdges = E;
graph->edges[0] = (Edge){0, 1, 6};
graph->edges[1] = (Edge){0, 2, 5};
graph->edges[2] = (Edge){0, 3, 5};
82
graph->edges[3] = (Edge){1, 4, -1};
graph->edges[4] = (Edge){2, 1, -2};
graph->edges[5] = (Edge){2, 4, 1};
graph->edges[6] = (Edge){3, 2, -2};
graph->edges[7] = (Edge){3, 5, -1};
graph->edges[8] = (Edge){4, 6, 3};
graph->edges[9] = (Edge){5, 6, 3};
graph->edges[10] = (Edge){6, 7, 2};
graph->edges[11] = (Edge){7, 8, -5};
graph->edges[12] = (Edge){8, 9, 2};
graph->edges[13] = (Edge){9, 3, 1};
graph->edges[14] = (Edge){4, 9, 2};
return graph;
}
void BellmanFord(Graph* graph, int src) {
int numVertices = graph->numVertices;
int numEdges = graph->numEdges;
int dist[numVertices];
for (int i = 0; i < numVertices; i++)
dist[i] = INT_MAX;
dist[src] = 0;
for (int i = 1; i <= numVertices - 1; i++) {
for (int j = 0; j < numEdges; j++) {
int u = graph->edges[j].src;
83
int v = graph->edges[j].dest;
int w = graph->edges[j].weight;
if (dist[u] != INT_MAX && dist[u] + w < dist[v])
dist[v] = dist[u] + w;
}
}
for (int j = 0; j < numEdges; j++) {
int u = graph->edges[j].src;
int v = graph->edges[j].dest;
int w = graph->edges[j].weight;
if (dist[u] != INT_MAX && dist[u] + w < dist[v]) {
printf("Graph contains a negative weight cycle\n");
return;
}
}
printf("Vertex Distance from Source %d\n", src);
for (int i = 0; i < numVertices; i++)
printf("%d\t\t%d\n", i, dist[i]);
}
int main() {
Graph* graph = createGraph();
BellmanFord(graph, 0);
free(graph);
return 0;
84
}
Output: Graph contains a negative weight cycle
19. Create Floyd-Warshall algorithm for finding all pairs shortest
paths in a graph with 5 vertices and 10 edges, and compare its
performance with Dijkstra's algorithm
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#define V 5
#define E 10
#define INF 1000000
int graph[V][V];
void initGraph() {
for(int i = 0; i < V; i++)
for(int j = 0; j < V; j++)
if(i == j) graph[i][j] = 0;
else graph[i][j] = INF;
int edges[E][3] = {
{0,1,3}, {0,2,8}, {0,4,-4}, {1,3,1}, {1,4,7},
{2,1,4}, {3,0,2}, {3,2,-5}, {4,3,6}, {2,4,2}
};
for(int i = 0; i < E; i++) {
int u = edges[i][0];
85
int v = edges[i][1];
int w = edges[i][2];
graph[u][v] = w;
}
}
void floydWarshall() {
int dist[V][V];
for(int i = 0; i < V; i++)
for(int j = 0; j < V; j++)
dist[i][j] = graph[i][j];
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] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
printf("Floyd-Warshall All-Pairs Shortest Paths:\n");
for(int i = 0; i < V; i++) {
for(int j = 0; j < V; j++) {
if(dist[i][j] == INF) printf("INF ");
else printf("%d ", dist[i][j]);
}
printf("\n");
}
}
86
void dijkstra(int src) {
int dist[V];
int visited[V] = {0};
for(int i = 0; i < V; i++)
dist[i] = INF;
dist[src] = 0;
for(int count = 0; count < V-1; count++) {
int min = INF, u;
for(int i = 0; i < V; i++)
if(!visited[i] && dist[i] <= min) {
min = dist[i];
u = i;
}
visited[u] = 1;
for(int v = 0; v < V; v++)
if(!visited[v] && graph[u][v] != INF &&
dist[u] + graph[u][v] < dist[v])
dist[v] = dist[u] + graph[u][v];
}
printf("Dijkstra from vertex %d:\n", src);
for(int i = 0; i < V; i++) {
if(dist[i] == INF) printf("INF ");
else printf("%d ", dist[i]);
}
87
printf("\n");
}
int main() {
initGraph();
clock_t start, end;
start = clock();
floydWarshall();
end = clock();
double fw_time = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("Floyd-Warshall Time: %f seconds\n", fw_time);
start = clock();
for(int i = 0; i < V; i++)
dijkstra(i);
end = clock();
double dj_time = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("Dijkstra (all sources) Time: %f seconds\n", dj_time);
return 0;
}
88
Output:
Floyd-Warshall All-Pairs Shortest Paths:
0 1 -3 2 -4
3 0 -4 1 -2
74052
2 -1 -5 0 -3
85160
Floyd-Warshall Time: 0.000054 seconds
Dijkstra from vertex 0:
0 1 -3 2 -4
Dijkstra from vertex 1:
3 0 -4 1 -2
Dijkstra from vertex 2:
74052
Dijkstra from vertex 3:
2 -1 -5 0 -3
Dijkstra from vertex 4:
85160
Dijkstra (all sources) Time: 0.000029 seconds
89
20. Implement Kruskal's algorithm to find the minimum spanning
tree of a graph with 10 vertices and 15 edges, and analyze its
efficiency
#include <stdio.h>
#include <stdlib.h>
#define V 10
#define E 15
typedef struct {
int u, v;
int weight;
} Edge;
typedef struct {
int parent;
int rank;
} Subset;
int find(Subset subsets[], int i) {
if (subsets[i].parent != i)
subsets[i].parent = find(subsets, subsets[i].parent);
return subsets[i].parent;
}
void Union(Subset subsets[], int x, int y) {
int xroot = find(subsets, x);
int yroot = find(subsets, y);
90
if (subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if (subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
else {
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
int compare(const void* a, const void* b) {
return ((Edge*)a)->weight - ((Edge*)b)->weight;
}
void kruskal(Edge edges[]) {
Edge result[V-1];
int e = 0;
int i = 0;
qsort(edges, E, sizeof(edges[0]), compare);
Subset subsets[V];
for (int v = 0; v < V; v++) {
subsets[v].parent = v;
subsets[v].rank = 0;
}
while (e < V - 1 && i < E) {
Edge next_edge = edges[i++];
91
int x = find(subsets, next_edge.u);
int y = find(subsets, next_edge.v);
if (x != y) {
result[e++] = next_edge;
Union(subsets, x, y);
}
}
printf("Edges in MST:\n");
int totalWeight = 0;
for (i = 0; i < e; i++) {
printf("%d -- %d == %d\n", result[i].u, result[i].v,
result[i].weight);
totalWeight += result[i].weight;
}
printf("Total weight of MST: %d\n", totalWeight);
}
int main() {
Edge edges[E] = {
{0,1,4}, {0,7,8}, {1,2,8}, {1,7,11}, {2,3,7},
{2,8,2}, {2,5,4}, {3,4,9}, {3,5,14}, {4,5,10},
{5,6,2}, {6,7,1}, {6,8,6}, {7,8,7}, {3,6,9}
};
kruskal(edges);
return 0;
92
}
Output:
Edges in MST:
6 -- 7 == 1
2 -- 8 == 2
5 -- 6 == 2
0 -- 1 == 4
2 -- 5 == 4
2 -- 3 == 7
0 -- 7 == 8
3 -- 4 == 9
Total weight of MST: 37
93
21. Develop Prim's algorithm for minimum spanning trees and
compare its performance with Kruskal's algorithm on a graph
with 10 vertices and 15 edges
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#define V 10
#define E 15
#define INF 999999
typedef struct {
int src, dest, weight;
} Edge;
typedef struct {
int parent;
int rank;
} Subset;
int compareEdges(const void *a, const void *b) {
Edge *e1 = (Edge *)a;
Edge *e2 = (Edge *)b;
return e1->weight - e2->weight;
}
int find(Subset subsets[], int x) {
if (subsets[x].parent != x)
94
subsets[x].parent = find(subsets, subsets[x].parent);
return subsets[x].parent;
}
void unionSet(Subset subsets[], int x, int y) {
int rootX = find(subsets, x);
int rootY = find(subsets, y);
if (subsets[rootX].rank < subsets[rootY].rank)
subsets[rootX].parent = rootY;
else if (subsets[rootX].rank > subsets[rootY].rank)
subsets[rootY].parent = rootX;
else {
subsets[rootY].parent = rootX;
subsets[rootX].rank++;
}
}
void kruskalMST(Edge edges[]) {
Edge result[V];
Subset subsets[V];
for (int v = 0; v < V; v++) {
subsets[v].parent = v;
subsets[v].rank = 0;
}
qsort(edges, E, sizeof(Edge), compareEdges);
int e = 0, i = 0, totalWeight = 0;
95
printf("\n--- Kruskal's MST ---\n");
while (e < V - 1 && i < E) {
Edge next = edges[i++];
int x = find(subsets, [Link]);
int y = find(subsets, [Link]);
if (x != y) {
result[e++] = next;
totalWeight += [Link];
unionSet(subsets, x, y);
}
}
for (int i = 0; i < e; i++)
printf("%d -- %d \tw=%d\n",
result[i].src, result[i].dest, result[i].weight);
printf("Total weight (Kruskal) = %d\n", totalWeight);
}
int minKey(int key[], int mstSet[]) {
int min = INF, min_index = -1;
for (int v = 0; v < V; v++)
if (!mstSet[v] && key[v] < min) {
min = key[v];
min_index = v;
}
return min_index;
96
}
void primMST(int graph[V][V]) {
int parent[V];
int key[V];
int mstSet[V] = {0};
for (int i = 0; i < V; i++)
key[i] = INF;
key[0] = 0;
parent[0] = -1;
printf("\n--- Prim's MST ---\n");
for (int count = 0; count < V - 1; count++) {
int u = minKey(key, mstSet);
mstSet[u] = 1;
for (int v = 0; v < V; v++)
if (graph[u][v] && !mstSet[v] && graph[u][v] < key[v]) {
parent[v] = u;
key[v] = graph[u][v];
}
}
int totalWeight = 0;
for (int i = 1; i < V; i++) {
printf("%d -- %d \tw=%d\n",
parent[i], i, graph[i][parent[i]]);
totalWeight += graph[i][parent[i]];
97
}
printf("Total weight (Prim) = %d\n", totalWeight);
}
int main() {
Edge edges[E] = {
{0, 1, 4}, {0, 7, 8}, {1, 2, 8},
{1, 7, 11}, {2, 3, 7}, {2, 8, 2},
{2, 5, 4}, {3, 4, 9}, {3, 5, 14},
{4, 5, 10}, {5, 6, 2}, {6, 7, 1},
{6, 8, 6}, {7, 8, 7}, {4, 8, 5}
};
int graph[V][V] = {0};
for (int i = 0; i < E; i++) {
int u = edges[i].src;
int v = edges[i].dest;
int w = edges[i].weight;
graph[u][v] = w;
graph[v][u] = w;
}
clock_t start, end;
start = clock();
kruskalMST(edges);
end = clock();
double kruskal_time = (double)(end - start) / CLOCKS_PER_SEC;
98
start = clock();
primMST(graph);
end = clock();
double prim_time = (double)(end - start) / CLOCKS_PER_SEC;
printf("\n--- Performance Comparison ---\n");
printf("Kruskal Time: %.6f seconds\n", kruskal_time);
printf("Prim Time: %.6f seconds\n", prim_time);
return 0;
}
Output:
--- Kruskal's MST ---
6 -- 7 w=1
2 -- 8 w=2
5 -- 6 w=2
0 -- 1 w=4
2 -- 5 w=4
4 -- 8 w=5
2 -- 3 w=7
0 -- 7 w=8
Total weight (Kruskal) = 33
99
--- Prim's MST ---
0 -- 1 w=4
1 -- 2 w=8
2 -- 3 w=7
8 -- 4 w=5
2 -- 5 w=4
5 -- 6 w=2
6 -- 7 w=1
2 -- 8 w=2
0 -- 9 w=0
Total weight (Prim) = 33
--- Performance Comparison ---
Kruskal Time: 0.000256 seconds
Prim Time: 0.000092 seconds
100
101
102
103
104
105
106
107
108