Wa0010.
Wa0010.
The objective of this lab is to teach students various data structures and to explain them the
importance of Data Structures in the context of writing algorithms for performing various
operations on these data structures. Students will gain practical knowledge by writing and
executing programs in C and C++ using learning the basic concepts related to the ‘C’ language
along with various data structures such as arrays, linked lists, stacks, queues, trees, graphs, hash
tables and search trees.
OUTCOMES:
Upon the completion of Data Structures practical course, the student will be able to:
1. Design and analyze the time and space efficiency of the data structure.
2. Identify the appropriate data structure for a given problem.
3. Understand the applications of data structures.
4. Choose the appropriate data structure and algorithm design method for a specified
application.
5. Understand which algorithm or data structure to use in different scenarios.
6. Understand and apply fundamental algorithmic problems including Tree traversals,
Graph traversals.
7. Compare different implementations of data structures and to recognize the
advantages and disadvantages of them.
8. Compare between different data structures. Pick an appropriate data structure for a
design situation.
The objective of this lab is to teach students various data structures and to explain them the
importance of Data Structures in context of writing algorithms for performing various
operations on these data structures. Students will gain practical knowledge by writing and
executing programs in C and C++ using various data structures such as arrays, linked lists,
stacks, queues, trees, graphs, hash tables and search trees.
Question: A university maintains ID, Name, Age, and Marks in 5 subjects for each student.
Write a program (any language) to input N students, compute each student’s Total and Grade
(use your own reasonable grading rules and state them), and display all toppers (handle ties).
Definition: A structure (record) groups heterogeneous attributes into one logical unit. It
improves organization, readability, and manipulation of related data. Structures model real-
world entities like students, employees, and products.
Pseudocode:
STUDENT_INFORMATION():
1. Define a record type STUDENT with fields: id, name, age
2. Create a variable student of type STUDENT
3. Prompt and read: [Link], [Link], [Link]
4. Display [Link], [Link], [Link] in a readable format
5. End
Test Cases:
N = 5
(ID, Name, Age, Marks[5])
S101, Arjun, 19, [95, 92, 88, 91, 94]
S102, Beena, 20, [78, 85, 80, 79, 81]
S103, Charan, 19, [67, 72, 70, 65, 68]
S104, Diya, 20, [89, 90, 92, 85, 87]
S105, Ethan, 21, [50, 60, 55, 58, 62]
Expected Output (example rubric: Avg ≥90: O; 80–89: A; 70–79: B; 60–69: C; else F)
Topper(s):
S101 Arjun Total=460 Grade=O
Expected Output
Topper(s):
S201 Kiran Total=450 Grade=O
S202 Leela Total=450 Grade=O
Result:
Question: A company maintains Employee(ID, Name, Department, Salary) and must support
large-scale operations:
Definition: Using pointers with structures allows for dynamic memory allocation and efficient
management of data. Pointers can be used to create and manipulate structure instances
dynamically and pass structures to functions without copying the entire structure. This can lead
to more efficient memory usage and function operations.
Aim: To manage entity records by creating, accessing, and releasing them dynamically at
runtime.
Pseudocode:
STUDENT_RECORD_DYNAMIC():
1. Define a record type STUDENT with fields: id, name, age
2. Dynamically create a new STUDENT record → ref_student
3. Prompt and read: ref_student.id, ref_student.name, ref_student.age
4. Display all fields of ref_student
5. Release (free) the dynamically created STUDENT record
6. End
Test Cases
8
ADD 501 Anu IT 60000
LIST IT:
501 Anu IT 60000
503 Charu IT 75000
DEL 502:
Deleted
LIST ALL:
501 Anu IT 60000
503 Charu IT 75000
504 Devi Finance 80000
7
ADD 610 Ravi Finance 90000
ADD 615 Rhea Finance 90000
ADD 620 Zara IT 85000
MAX ALL
DEL 699
DEL 610
MAX ALL
Expected Output
MAX ALL:
Finance: 610 Ravi 90000 // tie, lower ID chosen
IT: 620 Zara 85000
DEL 699:
DEL 610:
Deleted
MAX ALL:
Finance: 615 Rhea 90000
IT: 620 Zara 85000
Result:
Question: A research lab processes very large matrices (up to 1000×1000) with dimensions
known only at runtime. Write a program (any language) that reads such matrices, multiplies
them using dynamically allocated memory, and reports execution time for multiple input sizes.
Compare standard row–column multiplication with block (tiled) multiplication.
Definition: Matrix multiplication involves multiplying two matrices to produce a new matrix.
Dynamic memory allocation allows creating matrices whose size can be determined at runtime,
providing flexibility in handling different matrix dimensions. This technique involves
allocating memory dynamically for matrices and performing the multiplication operation.
Pseudocode:
MATRIX_MULTIPLY_DYNAMIC():
1. Read r1, c1 // size of Matrix A
2. Read r2, c2 // size of Matrix B
3. If c1 ≠ r2:
Display "Multiplication not possible"
Exit
4. Dynamically allocate:
A as r1 × c1
B as r2 × c2
C as r1 × c2 (initialized to 0)
5. Read all elements of A
6. Read all elements of B
7. For i ← 1 to r1:
For j ← 1 to c2:
sum ← 0
For k ← 1 to c1:
sum ← sum + A[i, k] × B[k, j]
C[i, j] ← sum
8. Display C
9. Release A, B, and C
10. End
A (2×3):
1 2 3
4 5 6
B (3×2):
7 8
9 10
11 12
Expected Output
C = A × B (2×2):
58 64
139 154
Input
A (2×2):
1 2
3 4
B (3×2):
5 6
7 8
9 10
Expected Output
Result:
Question: You are building a course enrollment roster. The list must support commands:
APPEND x, INSERT p x, REMOVE p, FIND x, DEDUP (remove duplicates, keep first occurrence,
preserve order), and RESIZE (double capacity when full and continue). Process a stream of M
commands and print the final roster and the positions returned by all FIND operations.
Definition: An array-based list is a linear data structure that stores elements in contiguous
memory locations. It provides efficient access to elements using indices but requires a fixed
size. The array implementation of a list supports basic operations like insertion, deletion, and
traversal.
Aim: To store and manipulate a sequence of elements using a contiguous array-based list.
Pseudocode:
ARRAY_LIST_OPERATIONS(capacity):
1. Create array L[1 … capacity]; size ← 0
2. INSERT_AT_END(x):
2.1 If size = capacity → Report "Overflow"; return
2.2 size ← size + 1
2.3 L[size] ← x
5. FIND(x):
5.1 For i ← 1 to size:
If L[i] = x → return i
5.2 return NOT_FOUND
6. DISPLAY():
Test Cases
capacity = 5
Commands (in order):
APPEND 10
APPEND 20
APPEND 30
INSERT 2 20
APPEND 10
DEDUP
FIND 30
DISPLAY
Expected Output
FIND 30 → 3
LIST → [10, 20, 30]
capacity = 3
Commands:
APPEND 5
APPEND 6
APPEND 7
APPEND 8 // triggers RESIZE internally (double capacity)
INSERT 2 9
REMOVE 4
DISPLAY
Expected Output
LIST → [5, 9, 6, 8]
Result:
List data structure operations (insertion, deletion, and display) are implemented
successfully using arrays.
Question:
Design a hospital triage queue using a singly linked list with two priority classes: URGENT and
REGULAR. Operations: ARRIVE name priority, SERVE (serve from URGENT if non-empty, else
REGULAR), CANCEL name, UPGRADE name (move a REGULAR patient to the end of URGENT while
preserving relative order within each class), and LIST. Handle up to 10⁵ operations efficiently.
Definition: A linked list is a linear data structure consisting of nodes where each node points
to the next node in the sequence. It allows for dynamic memory allocation and efficient
insertions and deletions at various positions. Each node contains data and a pointer to the next
node.
Aim: To manage a dynamic sequence of nodes using next-links for flexible insertions and
deletions.
Pseudocode:
SINGLY_LINKED_LIST():
1. Define record NODE { data, next }
2. head ← NIL
3. APPEND(x):
3.1 new ← NODE(x, NIL)
3.2 If head = NIL → head ← new; return
3.3 p ← head; while [Link] ≠ NIL: p ← [Link]
3.4 [Link] ← new
4. INSERT_AFTER(key, x):
4.1 p ← head; while p ≠ NIL and [Link] ≠ key: p ← [Link]
4.2 If p = NIL → Report "Key not found"; return
4.3 new ← NODE(x, [Link]); [Link] ← new
6. REVERSE():
6.1 prev ← NIL; curr ← head
6.2 while curr ≠ NIL:
next ← [Link]
[Link] ← prev
prev ← curr
curr ← next
6.3 head ← prev
7. DISPLAY():
7.1 p ← head; print [Link] in order until NIL
8. End
Test Cases
Result:
Singly linked list operations (insertion, deletion, and traversal) are implemented
successfully.
Question: Implement a browser history manager with capacity N using a doubly linked list.
Operations:
VISIT url (append after current; discard forward history), BACK k, FORWARD k, CURRENT, and
capacity control (if size exceeds N, drop the oldest page from the head). Output the current page
after each navigation command and the entire history (forward/backward) on HISTORY.
Definition: A doubly linked list is a linear data structure where each node contains data, a
pointer to the next node, and a pointer to the previous node. This allows traversal in both
directions and more flexibility in insertion and deletion.
Aim: To support bidirectional traversal and efficient deletions using prev/next links.
Pseudocode:
DOUBLY_LINKED_LIST():
1. Define record DNODE { data, prev, next }
2. head ← NIL; tail ← NIL
3. INSERT_END(x):
3.1 new ← DNODE(x, tail, NIL)
3.2 If head = NIL → head ← new; tail ← new; return
3.3 [Link] ← new; tail ← new
5. TRAVERSE_FORWARD():
5.1 p ← head; print [Link] → … → NIL
6. TRAVERSE_BACKWARD():
6.1 p ← tail; print [Link] → … → NIL
7. End
N = 5
VISIT [Link]
VISIT [Link]
VISIT [Link]
BACK 1
CURRENT
FORWARD 1
CURRENT
HISTORY
Expected Output
CURRENT → [Link]
CURRENT → [Link]
HISTORY → [[Link], [Link], [Link]] // forward/back are consistent
Input
N = 3
VISIT [Link]
VISIT [Link]
VISIT [Link]
BACK 2 // now at [Link]
VISIT [Link] // forward (b,c) discarded
VISIT [Link] // capacity 3 → drop oldest ([Link])
HISTORY
CURRENT
Expected Output
Result:
Doubly linked list operations (insertion, deletion, and traversal) are implemented
successfully.
Question: Build an Undo/Redo system for a text editor using stacks. Operations:
TYPE str (append str to the end), UNDO k, REDO k, PRINT, RESET (clear doc and history).
Constraints: maintain bounded history size M (the oldest actions are dropped when capacity
exceeds M). After any TYPE, the redo history must be cleared.
Definition: A stack is a linear data structure that follows the LIFO (Last In, First Out) principle.
It supports two primary operations: push to add an element and pop to remove the most recently
added element.
Aim: To implement a stack using arrays and perform basic operations like push, pop, and
display.
Pseudocode STACK_ARRAY
STACK_ARRAY(capacity):
1. Create array S[1 … capacity]; top ← 0
2. EMPTY():
return (top = 0)
3. FULL():
return (top = capacity)
4. PUSH(x):
4.1 If FULL() → report "Overflow" and return
4.2 top ← top + 1; S[top] ← x
5. POP():
5.1 If EMPTY() → report "Underflow" and return ⊥
5.2 x ← S[top]; top ← top - 1; return x
6. PEEK():
6.1 If EMPTY() → return ⊥
6.2 return S[top]
7. DISPLAY():
7.1 Print S[top], S[top-1], …, S[1]
STACK_LINKED():
1. Define record NODE { value, next }
2. top ← NIL
3. EMPTY():
return (top = NIL)
4. PUSH(x):
4.1 new ← NODE(x, top)
4.2 top ← new
5. POP():
5.1 If EMPTY() → report "Underflow" and return ⊥
5.2 x ← [Link]; top ← [Link]; return x
6. PEEK():
6.1 If EMPTY() → return ⊥
6.2 return [Link]
7. DISPLAY():
7.1 p ← top; print [Link] downward until NIL
Test Cases
M = 5
TYPE "hi"
TYPE " there"
PRINT
UNDO 1
PRINT
REDO 1
PRINT
"hi there"
"hi"
"hi there"
M = 3
TYPE "A"
TYPE "B"
TYPE "C"
UNDO 2 // doc: "A"
TYPE "D" // clears redo ("B","C"), history bounded to last 3
actions
PRINT
Expected Output
"AD"
Result:
The stack is successfully implemented using a linked list, and basic operations like
push, pop, and display are demonstrated.
Question:
Implement a print server with a queue of jobs, each with (JobID, Pages). Operations:
ENQUEUE id pages, SERVE p (print up to p pages from the job at front; if pages remain, requeue
job with remaining pages), CANCEL id (remove job wherever it is), STATUS (list jobs in order).
Support both circular array (bounded capacity) and linked (unbounded) implementations.
Definition: A queue is a linear data structure that follows the FIFO (First In, First Out)
principle. It supports two primary operations: enqueue to add an element at the rear and
dequeue to remove an element from the front.
Aim: To implement a queue using arrays and perform basic operations like enqueue, dequeue,
and display.
Pseudocode: CIRCULAR_QUEUE_ARRAY
CIRCULAR_QUEUE_ARRAY(capacity):
1. Create array Q[0 … capacity-1]; front ← 0; size ← 0
2. EMPTY():
return (size = 0)
3. FULL():
return (size = capacity)
4. ENQUEUE(x):
4.1 If FULL() → report "Overflow" and return
4.2 rear_index ← (front + size) mod capacity
4.3 Q[rear_index] ← x; size ← size + 1
5. DEQUEUE():
5.1 If EMPTY() → report "Underflow" and return ⊥
5.2 x ← Q[front]; front ← (front + 1) mod capacity; size ← size - 1;
return x
6. FRONT():
7. DISPLAY():
7.1 Print Q[(front + i) mod capacity] for i = 0 … size-1
Pseudocode: C_QUEUE_LINKED
QUEUE_LINKED():
1. Define record NODE { value, next }
2. front ← NIL; rear ← NIL
3. EMPTY():
return (front = NIL)
4. ENQUEUE(x):
4.1 new ← NODE(x, NIL)
4.2 If EMPTY(): front ← new; rear ← new
else: [Link] ← new; rear ← new
5. DEQUEUE():
5.1 If EMPTY() → report "Underflow" and return ⊥
5.2 x ← [Link]; front ← [Link]
5.3 If front = NIL: rear ← NIL
5.4 return x
6. FRONT():
6.1 If EMPTY() → return ⊥
6.2 return [Link]
7. DISPLAY():
7.1 p ← front; print [Link] … until NIL
Test Cases
ENQUEUE J1 7
ENQUEUE J2 4
SERVE 5
STATUS
SERVE 3
ENQUEUE A 10
ENQUEUE B 5
ENQUEUE C 8
CANCEL B
STATUS
SERVE 6
STATUS
Expected Output
STATUS → [A:10, C:8]
STATUS → [C:8, A:4]
Result:
Definition: Infix expressions are written with operators between operands (e.g., A + B), while
postfix expressions have operators after operands (e.g., AB+). Stacks are used in this
conversion to handle operator precedence and parentheses effectively.
Pseudocode:
INFIX_TO_POSTFIX(expr):
1. output ← empty list; stack ← empty
2. For each token t in expr (left → right):
2.1 If t is operand → append t to output
2.2 Else if t = '(' → PUSH '(' onto stack
2.3 Else if t = ')' → POP operators to output until '(' is on top;
POP '('
2.4 Else t is operator op:
while stack not empty and TOP is operator and
(prec(TOP) > prec(op) or
(prec(TOP) = prec(op) and assoc(op) = LEFT)):
append POP() to output
PUSH op
3. While stack not empty: append POP() to output
4. return output as a postfix string
Test Cases
Infix: A * (B + C) / D
Values: A=6, B=2, C=3, D=5
Expected Output
Expected Output
Postfix: A NEG B C ^ ^ // or equivalent encoding of unary minus
Value: -64 // -(2^(3^2)) = -(2^9) = -512 (If unary
binds tightest;
// adjust to your defined precedence →
demonstrate in rubric)
Result:
Extend the scheduler with aging: every T units of waiting in the ready set, increase a process’s
priority by 1 (to reduce starvation). Output the execution order, waiting/turnaround of each
process, and the average metrics.
PRIORITY_SCHEDULER(processes):
// Each process p: (id, arrival, burst, priority)
n = 3
(id, arrival, burst, priority)
P1 0 8 2
P2 1 4 3
P3 2 2 3
T (aging) = ∞ // no aging
Expected Output
Result:
Question: You are given a level-order array for a (possibly sparse) binary tree using -1 as
NULL.
Support queries:
Definition: A binary tree is a hierarchical data structure where each node has at most two
children, referred to as the left child and the right child. Representing a binary tree using an
array involves storing nodes in specific indices such that the parent-child relationships are
maintained.
Aim: To implement a binary tree using an array and perform basic operations like insertion,
traversal, and display.
Pseudocode:
BINARY_TREE_ARRAY():
1. Let T[1 … CAP] be an array (initialize all to NULL)
2. BUILD_LEVEL_ORDER(L): // L is list of values in level order, may
contain NULL
2.1 n ← min(|L|, CAP)
2.2 For i ← 1 to n: T[i] ← L[i]
3. INORDER(i):
3.1 If i > CAP or T[i] = NULL: return
3.2 INORDER(2i)
3.3 VISIT(T[i])
3.4 INORDER(2i+1)
4. PREORDER(i):
4.1 If i > CAP or T[i] = NULL: return
4.2 VISIT(T[i])
4.3 PREORDER(2i)
4.4 PREORDER(2i+1)
5. POSTORDER(i):
Test Cases
CAP = 15
Level order L (1-based positions):
[10, 20, 30, 40, 50, -1, 70, -1, -1, 90, -1, -1, -1, -1, 100]
Q:
TRAVERSAL IN
TRAVERSAL PRE
TRAVERSAL POST
LEAFCOUNT
Expected Output
IN → 40 20 90 50 10 30 70 100
PRE → 10 20 40 50 90 30 70 100
POST → 40 90 50 20 100 70 30 10
LEAFCOUNT → 4
Expected Output
ANCESTORS 11 → 50 20 10
Result:
Binary tree operations (insertion and traversal) are implemented successfully using an
array.
Question: Build a student registry keyed by RollNo (integers). Support operations: ADD k,
DEL k, FIND k, PRINTSORTED, and RANGE L R (print keys in [L, R]).
Reject duplicate inserts. Process up to 10⁵ operations and print outputs for queries.
Definition: A Binary Search Tree (BST) is a binary tree where each node's value is greater
than the values in its left subtree and smaller than the values in its right subtree. Using linked
lists allows dynamic allocation of nodes, enabling efficient memory usage and flexible tree
operations.
Aim: To implement a Binary Search Tree (BST) using a linked list and perform operations like
insertion, deletion, and traversal.
Pseudocode:
BST_LINKED():
1. Define record NODE { key, left, right }
2. root ← NIL
3. INSERT(root, k):
3.1 If root = NIL: return NODE(k, NIL, NIL)
3.2 If k < [Link]: [Link] ← INSERT([Link], k)
Else if k > [Link]: [Link] ← INSERT([Link], k)
Else // duplicate: ignore or handle policy
3.3 return root
4. SEARCH(root, k):
4.1 If root = NIL or [Link] = k: return root
4.2 If k < [Link]: return SEARCH([Link], k)
Else: return SEARCH([Link], k)
6. FIND_MIN(x):
6.1 while [Link] ≠ NIL: x ← [Link]
6.2 return x
8. RANGE_QUERY(root, L, R):
8.1 If root = NIL: return
8.2 If [Link] > L: RANGE_QUERY([Link], L, R)
8.3 If L ≤ [Link] ≤ R: VISIT([Link])
8.4 If [Link] < R: RANGE_QUERY([Link], L, R)
Test Cases
ADD 50
ADD 30
ADD 70
ADD 20
ADD 40
ADD 60
ADD 80
PRINTSORTED
FIND 40
FIND 35
DEL 70
PRINTSORTED
RANGE 25 65
Expected Output
PRINTSORTED → 20 30 40 50 60 70 80
FIND 40 → FOUND
FIND 35 → NOTFOUND
PRINTSORTED → 20 30 40 50 60 80
RANGE 25 65 → 30 40 50 60
Expected Output
ADD 10 → OK
ADD 10 → DUPLICATE
PRINTSORTED → 15
Result:
Binary Search Tree operations (insertion, deletion, and traversal) are implemented
successfully using a linked list.
Question: Build a page-oriented index for unique integer keys using a B-Tree with minimum
degree t. Support operations: INSERT k, SEARCH k, and PRINT (in-order traversal of keys).
Assume keys are inserted in arbitrary order (no duplicates). Print search result and the final in-
order sequence.
Definition: A B-Tree is a self-balancing search tree that maintains sorted data and allows
searches, sequential access, insertions, and deletions in logarithmic time. It is widely used in
databases and file systems.
Aim: To implement a B-Tree and perform operations such as insertion and traversal.
Pseudocode:
B_TREE():
1. Define record NODE { keys[ ], child[ ], n, leaf } // n = #keys
2. Create empty root: NODE with leaf = TRUE, n = 0
6. INSERT_NONFULL(x, k):
6.1 i ← x.n
6.2 If [Link] = TRUE:
while i ≥ 1 and k < [Link][i]:
[Link][i+1] ← [Link][i]; i ← i - 1
[Link][i+1] ← k; x.n ← x.n + 1
Else:
while i ≥ 1 and k < [Link][i]: i ← i - 1
i ← i + 1
If [Link][i].n = 2t - 1:
SPLIT_CHILD(x, i, [Link][i])
If k > [Link][i]: i ← i + 1
INSERT_NONFULL([Link][i], k)
Test Cases
t = 2
INSERT keys: 10, 20, 5, 6, 12, 30, 7, 17
SEARCH 6
SEARCH 25
PRINT
Expected Output
SEARCH 6 → FOUND
SEARCH 25 → NOTFOUND
PRINT → 5 6 7 10 12 17 20 30
Expected Output
PRINT → 1 2 3 4 5 6 7 8 9 10
Result:
Question: A campus app models buildings as vertices and walkways as undirected edges.
Given multiple queries: BFS s, DFS s, and REACH s t (YES/NO), build the graph in both
forms, answer using the adjacency list, and print each result in ascending-neighbor order.
Definition: A graph is a data structure that consists of a set of vertices (nodes) and edges
(connections) between them. An adjacency matrix is a 2D array where the presence of an edge
between two vertices is represented by a non-zero value.
Aim: To implement a graph using an adjacency matrix and perform operations such as adding
edges and displaying the graph.
Pseudocode:
BFS(Adj, n, s):
1. visited[1..n] ← FALSE; order ← empty
2. Create empty queue Q; visited[s] ← TRUE; ENQUEUE(Q, s)
3. While Q not empty:
3.1 u ← DEQUEUE(Q); append u to order
3.2 For each v in Adj[u] (ascending):
If visited[v] = FALSE:
visited[v] ← TRUE; ENQUEUE(Q, v)
4. Return order
DFS(Adj, n, s):
1. visited[1..n] ← FALSE; order ← empty
2. Procedure VISIT(u):
2.1 visited[u] ← TRUE; append u to order
Test Cases
Expected Output
BFS 1 → 1 2 3 4 5 6
DFS 1 → 1 2 4 5 3 6
REACH 4 6 → YES
Input
Expected Output
BFS 2 → 2 1 3 4
DFS 2 → 2 1 3 4
REACH 2 5 → NO
Result:
Question: A delivery company has a road network with non-negative travel times.
For multiple queries SRC s, DIST t, PATH t, compute once from s using Dijkstra, then answer
distance and path requests (if unreachable, print UNREACHABLE). Support repeated new sources
by re-running Dijkstra.
Aim: To implement Dijkstra's algorithm for finding the shortest path from a source vertex to
all other vertices in a graph.
Pseudocode:
DIJKSTRA(AdjW, n, s):
// AdjW[u] = list of (v, w), with w ≥ 0
1. For i ← 1..n: dist[i] ← ∞; parent[i] ← NIL
2. dist[s] ← 0
3. Create empty min-priority-queue PQ; INSERT (0, s)
4. While PQ not empty:
4.1 (d, u) ← EXTRACT_MIN(PQ)
4.2 If d > dist[u]: continue // skip stale pair
4.3 For each (v, w) in AdjW[u]:
If dist[u] + w < dist[v]:
dist[v] ← dist[u] + w
parent[v] ← u
INSERT (dist[v], v) into PQ
5. Return (dist, parent)
PATH(s, t, parent):
1. If dist[t] = ∞: return "UNREACHABLE"
2. P ← empty list; x ← t
3. While x ≠ NIL: prepend x to P; x ← parent[x]
4. Return P
Expected Output
Input
Expected Output
DIST 4 → UNREACHABLE
PATH 4 → UNREACHABLE
Result:
A city wants a lowest-cost fiber backbone across all junctions. You are given an undirected,
weighted graph of junctions and roads. Some ducts already exist and must be used, and some
streets are unavailable and must not be used.
• Input:
o Graph G=(V,E)G=(V,E)G=(V,E) with positive edge costs.
o A list REQUIRE of edges that must be included (pre-laid ducts).
o A list FORBID of edges that cannot be used (permits denied).
• Tasks:
1. Validate the REQUIRE set (it must not contain a cycle). If it does, print
INVALID_CONSTRAINTS.
2. Compute and print the MST edges and total cost using Kruskal, treating all
FORBID edges as removed and starting with all REQUIRE edges pre-selected.
3. If no spanning tree exists under these constraints, print NO_MST.
• Output:
o The chosen edges (u, v, w) in non-decreasing weight order (break ties by
lexicographic (u, v)).
Definition: A Minimum Spanning Tree (MST) of a graph is a subset of its edges that connects
all vertices with the minimum possible total edge weight, without forming any cycles. Kruskal's
algorithm uses a greedy approach to construct the MST by selecting edges with the lowest
weights first.
Aim: To implement Kruskal's algorithm for finding the minimum spanning tree (MST) of a
connected, weighted graph.
Pseudocode:
KRUSKAL_MST(n, edges):
// edges: list of (u, v, w), undirected; assume graph connected
1. Sort edges by weight ascending (stable tie-break by (u,v) ascending)
2. MakeSet(1..n) in DSU; MST ← empty list; total ← 0
3. For each (u, v, w) in edges (in order):
Input
n = 5
Edges:
(1,2,3) (1,3,4) (2,3,1) (2,4,2) (3,5,5) (4,5,1)
Expected Output
Input
n = 4
Edges:
(1,2,1) (1,3,1) (1,4,1) (2,3,1) (2,4,1) (3,4,1)
Expected Output
Total → 3
(Any three non-cycling edges of weight 1 form an MST; with the stated tie rule, the set
above is expected.)
Result:
A telecom rollout must start from a designated central exchange (start vertex sss). Using
Prim’s algorithm, plan the fiber network.
• Input:
o An undirected, weighted connected graph G=(V,E)G=(V,E)G=(V,E) with
positive edge costs.
o A start vertex sss (the hub).
o Optionally, a second start vertex s′s's′ to compare hub choices.
• Tasks:
1. Run Prim from sss and print:
§ The order in which vertices are added,
§ The selected edges (parent → child with edge weight),
§ The total MST cost.
2. If s′s's′ is provided, repeat and compare:
§ Show whether the edge set differs,
§ Report the cost difference Δ=cost(s′)−cost(s)\Delta = \text{cost}(s') -
\text{cost}(s)Δ=cost(s′)−cost(s).
3. If the graph is not connected, print NO_MST.
• Output:
o Sequence of added vertices with their chosen key/edge weight,
o Final MST edge list (u, v, w) and total cost,
o (If s′s's′ given) a short comparison summary including Δ\DeltaΔ.
Definition: Prim's algorithm builds the MST by starting from an arbitrary vertex and growing
the tree by adding the minimum weight edge connecting a vertex in the tree to a vertex outside
the tree.
Pseudocode:
PRIM_MST(AdjW, n, s):
1. inMST[1..n] ← FALSE; key[1..n] ← ∞; parent[1..n] ← NIL
2. key[s] ← 0
3. PQ ← empty min-PQ; INSERT (0, s)
4. total ← 0
5. While PQ not empty:
5.1 (k, u) ← EXTRACT_MIN(PQ)
5.2 If inMST[u] = TRUE: continue
5.3 inMST[u] ← TRUE; total ← total + k
5.4 For each (v, w) in AdjW[u]:
If inMST[v] = FALSE and w < key[v]:
key[v] ← w; parent[v] ← u; INSERT (key[v], v)
6. MST ← edges {(parent[v], v, key[v]) | v ≠ s}
7. Return (MST, total)
Input
n = 5
Edges:
(1,2,3) (1,3,4) (2,3,1) (2,4,2) (3,5,5) (4,5,1)
Start: 1
Expected Output
MST edges (one valid set) → (1,2,3) (2,3,1) (2,4,2) (4,5,1)
Total → 7
Input
n = 4
Edges:
(1,2,4) (2,3,1) // vertex 4 is isolated
Expected Output
NO_MST
Result: