0% found this document useful (0 votes)
2 views22 pages

MP-ANS

The document contains questions and answers related to data structures and algorithms, covering topics such as sparse matrices, recursion, stacks, binary search trees, graphs, queues, time complexity, and tree traversal methods. It includes detailed explanations, definitions, and examples for concepts like bubble sort, circular queues, the Towers of Hanoi problem, and dynamic memory allocation in C. Additionally, it discusses the adjacency matrix representation of graphs and provides algorithms and their complexities.

Uploaded by

eimrglck
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)
2 views22 pages

MP-ANS

The document contains questions and answers related to data structures and algorithms, covering topics such as sparse matrices, recursion, stacks, binary search trees, graphs, queues, time complexity, and tree traversal methods. It includes detailed explanations, definitions, and examples for concepts like bubble sort, circular queues, the Towers of Hanoi problem, and dynamic memory allocation in C. Additionally, it discusses the adjacency matrix representation of graphs and provides algorithms and their complexities.

Uploaded by

eimrglck
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/ 22

DS-STDY-M

Section – A

Answer any 10 questions. Each question carries 2 marks.

(10 × 2 = 20 Marks)

1. What are sparse matrices?

 A sparse matrix is a matrix in which most of the elements are zero.


 Storing only the non-zero elements along with their row and column indices can save
significant memory and computation time.

2. What is recursion?

 Recursion is a programming technique where a function calls itself, directly or indirectly, to


solve a problem.
 It breaks down a problem into smaller, similar sub-problems until a base case (which has a
direct solution) is reached.

3. Define a stack.

 A stack is a linear data structure that follows the Last-In, First-Out (LIFO) principle.
 Elements are added and removed only from one end, called the "top" of the stack.

4. What is a binary search tree?

 A binary search tree (BST) is a rooted binary tree data structure where each node has at most
two children, referred to as the left child and the right child.
 It maintains the property that for any given node, all values in its left subtree are less than the
node's value, and all values in its right subtree are greater than the node's value.

5. Define a graph.

 A graph is a non-linear data structure consisting of a set of vertices (or nodes) and a set of
edges (or arcs) connecting pairs of these vertices.
 It is used to represent relationships between discrete objects.

6. What is a circular queue?

 A circular queue is a linear data structure that operates similarly to a regular queue but with
the last element connected to the first element, forming a circle.
 This arrangement allows for efficient use of memory by reusing dequeued spaces at the front
of the queue.

7. Define time complexity.


 Time complexity is a measure of the amount of time taken by an algorithm to run as a
function of the length of the input.
 It quantifies the number of operations an algorithm performs, typically expressed using Big O
notation (e.g., O(n), O(log n)).

8. Compare stack and queue.

 Stack: Follows LIFO (Last-In, First-Out) principle. Operations are Push (add) and Pop
(remove) from the top.
 Queue: Follows FIFO (First-In, First-Out) principle. Operations are Enqueue (add) at the rear
and Dequeue (remove) from the front.

9. What is a non-linear data structure?

 A non-linear data structure is one where data elements are not arranged sequentially or
linearly.
 Each element can be connected to multiple other elements, allowing for complex
relationships (e.g., trees, graphs).

10. Mention different tree traversal methods.

 In-order Traversal: Visits the left subtree, then the root, then the right subtree (Left-Root-
Right).
 Pre-order Traversal: Visits the root, then the left subtree, then the right subtree (Root-Left-
Right).
 Post-order Traversal: Visits the left subtree, then the right subtree, then the root (Left-
Right-Root).

11. What is a priority queue?

 A priority queue is an abstract data type similar to a regular queue, but each element has a
"priority" associated with it.
 Elements with higher priority are served before elements with lower priority, or elements
with the same priority are served according to their order in the queue.

12. What are dynamic memory allocations?

 Dynamic memory allocation is the process of allocating memory at runtime (during program
execution) rather than at compile time.
 This allows programs to manage memory more flexibly, requesting memory as needed and
releasing it when no longer required (e.g., using malloc(), calloc(), realloc(), free() in
C).
Section – B

Answer any 6 questions. Each question carries 5 marks.

(6 × 5 = 30 Marks)

13. Explain tree traversal methods (Inorder, Preorder, Postorder) with an example.

Key Points:

 Tree traversal refers to the process of visiting each node in a tree data structure exactly once.
There are three common depth-first traversal methods.
 Example Tree:
 A
 / \
 B C
 / \
 D E
 1. Inorder Traversal (Left -> Root -> Right)
o Explanation: Traverse the left subtree, then visit the root node, and finally traverse the right
subtree. For Binary Search Trees, Inorder traversal yields elements in non-decreasing order.
o Output for Example: D B E A C
 2. Preorder Traversal (Root -> Left -> Right)
o Explanation: Visit the root node first, then traverse the left subtree, and finally traverse the
right subtree. This is useful for creating a copy of the tree or for prefix expressions.
o Output for Example: A B D E C
 3. Postorder Traversal (Left -> Right -> Root)
o Explanation: Traverse the left subtree, then traverse the right subtree, and finally visit the
root node. This is useful for deleting a tree or for postfix expressions.
o Output for Example: D E B C A

14. Write an algorithm for bubble sort and explain.

Key Points:

 Definition: Bubble sort is a simple sorting algorithm that repeatedly steps through the list,
compares adjacent elements, and swaps them if they are in the wrong order. The pass through
the list is repeated until no swaps are needed, which indicates that the list is sorted.
 Working Principle: In each pass, the largest unsorted element "bubbles up" to its correct
position at the end of the unsorted portion.
 Algorithm (Pseudocode):
 BubbleSort(arr, n)
 FOR i FROM 0 TO n-2 DO // Outer loop for passes
 swapped = FALSE
 FOR j FROM 0 TO n-2-i DO // Inner loop for comparisons and
swaps
 IF arr[j] > arr[j+1] THEN
 // Swap arr[j] and arr[j+1]
 temp = arr[j]
 arr[j] = arr[j+1]
 arr[j+1] = temp
 swapped = TRUE
 END IF
 END FOR
 IF swapped == FALSE THEN // Optimization: If no swaps in a
pass, array is sorted
 BREAK
 END IF
 END FOR
 END BubbleSort
 Explanation:
1. The outer loop runs n-1 times (where n is the number of elements), representing the number
of passes needed.
2. The inner loop iterates through the unsorted part of the array. The n-2-i ensures that already
sorted elements at the end are not re-compared.
3. It compares arr[j] with arr[j+1]. If arr[j] is greater, they are swapped.
4. A swapped flag is used for optimization: if a pass completes without any swaps, it means the
array is already sorted, and the algorithm can terminate early.
 Time Complexity:
o Best Case: O(n) (already sorted)
o Average Case: O(n^2)
o Worst Case: O(n^2)

15. Explain the concept of circular queue with diagram.

Key Points:

 Concept: A circular queue is a linear data structure, similar to a regular queue, but with the
last element connected to the first element, forming a circle. This allows for more efficient
use of memory space.
 Pointers: It uses two pointers: front (or head) and rear (or tail).
o front points to the starting element of the queue.
o rear points to the last element of the queue.
 Working:
o When an element is enqueued, rear is incremented circularly.
o When an element is dequeued, front is incremented circularly.
o The front and rear pointers "wrap around" to the beginning of the array when they reach
the end.
 Conditions:
o Queue Empty: front == -1 (initial state) or front == rear + 1 (after all elements are
dequeued and rear wraps around). Some implementations use front == rear and
differentiate with a counter or boolean flag.
o Queue Full: When the next position for rear (calculated circularly) becomes equal to front.
For example, (rear + 1) % MAX_SIZE == front.
 Advantages:
o Efficient memory utilization as unused slots at the beginning of the array can be reused.
o Avoids the "queue full" problem of linear queues where rear might reach the end of the
array even if front has advanced, leaving empty space at the beginning.
 Diagram:
 Initial Empty Queue (Size 5):
 [ ] [ ] [ ] [ ] [ ]
 0 1 2 3 4
 front = -1, rear = -1

 After Enqueue(10), Enqueue(20), Enqueue(30):
 [10][20][30][ ] [ ]
 0 1 2 3 4
 front = 0, rear = 2

 After Dequeue() (10 is removed):
 [ ] [20][30][ ] [ ]
 0 1 2 3 4
 front = 1, rear = 2

 After Enqueue(40), Enqueue(50):
 [ ] [20][30][40][50]
 0 1 2 3 4
 front = 1, rear = 4

 After Enqueue(60) (Wraps around):
 [60][20][30][40][50]
 0 1 2 3 4
 front = 1, rear = 0 (wrapped)

 Queue Full Condition:
 [60][70][80][90][50] (Example if front was at 1, rear at 0, and we try
to add 100)
 0 1 2 3 4
 front = 1, rear = 0
 (rear + 1) % MAX_SIZE = (0+1)%5 = 1, which is equal to front.

16. Explain the Towers of Hanoi problem with an example.

Key Points:

 Definition: The Towers of Hanoi is a classic mathematical puzzle or game. It consists of


three pegs (or rods) and a number of disks of different sizes, which can slide onto any peg.
 Objective: The puzzle starts with the disks in a neat stack in ascending order of size on one
peg, the smallest at the top, thus making a conical shape. The objective is to move the entire
stack to another peg, obeying the following rules:
1. Only one disk can be moved at a time.
2. Each move consists of taking the upper disk from one of the stacks and placing it on top of
another stack or on an empty peg.
3. No disk may be placed on top of a smaller disk.
 Recursive Solution: The problem has an elegant recursive solution.
o Base Case: If there is only one disk, move it directly from the source peg to the destination
peg.
o Recursive Step:
1. Move n-1 disks from the source peg to the auxiliary (helper) peg, using the destination
peg as auxiliary.
2. Move the largest (nth) disk from the source peg to the destination peg.
3. Move the n-1 disks from the auxiliary peg to the destination peg, using the source peg
as auxiliary.
 Example (N=3 disks):
o Pegs: Source (S), Auxiliary (A), Destination (D)
o Disks: 1 (Smallest), 2 (Medium), 3 (Largest) - Initially on Source (S)

<!-- end list -->

2. Move disk 1 from S to D. (S: [2,3], A: [], D: [1])


3. Move disk 2 from S to A. (S: [3], A: [2], D: [1])
4. Move disk 1 from D to A. (S: [3], A: [1,2], D: [])
5. Move disk 3 from S to D. (S: [], A: [1,2], D: [3])
6. Move disk 1 from A to S. (S: [1], A: [2], D: [3])
7. Move disk 2 from A to D. (S: [1], A: [], D: [2,3])
8. Move disk 1 from S to D. (S: [], A: [], D: [1,2,3])
 Number of Moves: For n disks, the minimum number of moves required is 2^n - 1. For 3
disks, it's 2^3 - 1 = 7 moves.

17. Explain dynamic memory allocation functions in C with example.

Key Points:

 Concept: Dynamic memory allocation in C allows programs to request and release memory
during runtime. This is crucial when the size of data structures is not known at compile time
or when memory needs to vary.
 Header: These functions are typically declared in the <stdlib.h> header file.
 Functions:
1. malloc() (Memory Allocation)
 Purpose: Allocates a block of memory of a specified size in bytes. It returns a void* pointer
to the beginning of the allocated block, or NULL if allocation fails. The allocated memory is
uninitialized (contains garbage values).
 Syntax: void* malloc(size_t size);
 Example:

C
int *ptr;
ptr = (int *) malloc(5 * sizeof(int)); // Allocates space for 5
integers
if (ptr == NULL) { /* handle error */ }
// Use ptr to access memory
free(ptr); // Release memory

2. calloc() (Contiguous Allocation)


 Purpose: Allocates a block of memory for an array of a specified number of elements, each
of a specified size. It initializes all bytes in the allocated block to zero. Returns void* or
NULL.
 Syntax: void* calloc(size_t num, size_t size);
 Example:

C
int *arr;
arr = (int *) calloc(10, sizeof(int)); // Allocates space for 10
integers, all initialized to 0
if (arr == NULL) { /* handle error */ }
// Use arr
free(arr); // Release memory

3. realloc() (Re-allocation)
 Purpose: Changes the size of an already allocated block of memory. It can either extend or
shrink the block. The contents of the old block are preserved up to the minimum of the old
and new sizes. Returns void* or NULL.
 Syntax: void* realloc(void* ptr, size_t new_size);
 Example:

C
int *ptr;
ptr = (int *) malloc(5 * sizeof(int)); // Allocate for 5 ints
// ... use ptr ...
ptr = (int *) realloc(ptr, 10 * sizeof(int)); // Reallocate for 10 ints
if (ptr == NULL) { /* handle error */ }
// Use updated ptr
free(ptr); // Release memory

4. free() (Deallocation)
 Purpose: Deallocates the memory block previously allocated by malloc(), calloc(), or
realloc(). Releasing memory is crucial to prevent memory leaks.
 Syntax: void free(void* ptr);
 Example: (See examples above for malloc, calloc, realloc where free is used)

18. Write a note on adjacency matrix representation of graphs.

Key Points:

 Definition: An adjacency matrix is a square matrix used to represent a finite graph. The rows
and columns are labeled with the graph's vertices.
 Structure: If a graph has n vertices, its adjacency matrix will be an n x n matrix, say Adj.
 Representation for Undirected Graph:
o Adj[i][j] = 1 if there is an edge between vertex i and vertex j.
o Adj[i][j] = 0 if there is no edge between vertex i and vertex j.
o For an undirected graph, the matrix is symmetric (Adj[i][j] == Adj[j][i]).
 Representation for Directed Graph:
o Adj[i][j] = 1 if there is a directed edge from vertex i to vertex j.
o Adj[i][j] = 0 if there is no directed edge from vertex i to vertex j.
o The matrix may not be symmetric.
 Representation for Weighted Graph:
o Instead of 1, Adj[i][j] stores the weight of the edge between vertex i and vertex j.
o 0 or infinity (or a very large number) can be used to indicate no edge.
 Example (Undirected Graph):
 Vertices: 0, 1, 2, 3
 Edges: (0,1), (0,2), (1,2), (2,3)

 Adjacency Matrix (4x4):
 0 1 2 3
 0 | 0 1 1 0
 1 | 1 0 1 0
 2 | 1 1 0 1
 3 | 0 0 1 0
 Advantages:
o Simple to implement and understand.
o Checking for an edge between two specific vertices (e.g., Adj[i][j]) is O(1) time
complexity.
o Adding or removing an edge is O(1).
 Disadvantages:
o Space Complexity: O(V^2) where V is the number of vertices. This can be very inefficient
for sparse graphs (graphs with few edges) as it stores many zeros.
o Finding all neighbors of a vertex requires iterating through an entire row or column (O(V)
time).

19. Write a C program to evaluate a postfix expression.

Key Points:

 Concept: Postfix expressions (Reverse Polish Notation) are evaluated using a stack.
Operands are pushed onto the stack, and when an operator is encountered, the top two
operands are popped, the operation is performed, and the result is pushed back onto the stack.
 Algorithm:
1. Create an empty stack.
2. Scan the postfix expression from left to right.
3. If the scanned character is an operand, push it onto the stack.
4. If the scanned character is an operator:
 Pop two operands from the stack (operand2 first, then operand1).
 Perform the operation (operand1 operator operand2).
 Push the result back onto the stack.
5. After scanning the entire expression, the value remaining on the stack is the result.
 C Program:

C
#include <stdio.h>
#include <stdlib.h> // For malloc, free, exit
#include <string.h> // For strlen
#include <ctype.h> // For isdigit

#define MAX_STACK_SIZE 100

// Stack structure
typedef struct {
int items[MAX_STACK_SIZE];
int top;
} Stack;

// Function to initialize the stack


void initStack(Stack *s) {
s->top = -1;
}

// Function to check if stack is empty


int isEmpty(Stack *s) {
return s->top == -1;
}

// Function to check if stack is full


int isFull(Stack *s) {
return s->top == MAX_STACK_SIZE - 1;
}

// Function to push an element onto the stack


void push(Stack *s, int value) {
if (isFull(s)) {
printf("Stack Overflow!\n");
exit(1); // Exit if stack is full
}
s->items[++s->top] = value;
}

// Function to pop an element from the stack


int pop(Stack *s) {
if (isEmpty(s)) {
printf("Stack Underflow!\n");
exit(1); // Exit if stack is empty
}
return s->items[s->top--];
}

// Function to perform arithmetic operations


int operate(char operator, int op1, int op2) {
switch (operator) {
case '+': return op1 + op2;
case '-': return op1 - op2;
case '*': return op1 * op2;
case '/':
if (op2 == 0) {
printf("Division by zero error!\n");
exit(1);
}
return op1 / op2;
default: return 0; // Should not happen for valid postfix
}
}

// Function to evaluate postfix expression


int evaluatePostfix(char* expression) {
Stack stack;
initStack(&stack);
int i;
int operand1, operand2, result;

for (i = 0; i < strlen(expression); i++) {


// Skip spaces
if (expression[i] == ' ' || expression[i] == '\t') {
continue;
}

// If operand (digit), push to stack


if (isdigit(expression[i])) {
push(&stack, expression[i] - '0'); // Convert char digit to
int
}
// If operator, pop two operands, operate, push result
else {
operand2 = pop(&stack);
operand1 = pop(&stack);
result = operate(expression[i], operand1, operand2);
push(&stack, result);
}
}

// The final result is the only element left on the stack


return pop(&stack);
}

int main() {
char expression[] = "231*+9-"; // Example: (2 + (3 * 1)) - 9 = (2 +
3) - 9 = 5 - 9 = -4
// char expression[] = "5 3 + 6 2 / *"; // Example: (5+3) * (6/2) =
8 * 3 = 24

printf("Postfix Expression: %s\n", expression);


int result = evaluatePostfix(expression);
printf("Result: %d\n", result);

return 0;
}

20. Write an algorithm to insert and delete an element in a linear queue.

Key Points:
 Concept: A linear queue is a FIFO (First-In, First-Out) data structure where elements are
inserted at one end (rear) and deleted from the other end (front).
 Pointers: Uses front and rear pointers.
o front: Points to the first element.
o rear: Points to the last element.
o Initially, front = -1 and rear = -1 for an empty queue.
 Assumptions:
o The queue is implemented using an array queue[MAX_SIZE].
o MAX_SIZE is the maximum capacity of the queue.
 1. Enqueue (Insertion) Algorithm:
o Purpose: To add an element to the rear of the queue.
o Algorithm:
1. Check for Queue Full (Overflow): If rear == MAX_SIZE - 1, print "Queue Overflow" and
return.
2. Handle Empty Queue: If front == -1 (queue is initially empty), set front = 0.
3. Increment Rear: Increment rear by 1 (rear = rear + 1).
4. Insert Element: Place the ITEM at queue[rear].
o Pseudocode:
o ENQUEUE(queue, front, rear, MAX_SIZE, ITEM)
o IF rear == MAX_SIZE - 1 THEN
o PRINT "Queue Overflow"
o RETURN
o END IF
o
o IF front == -1 THEN
o front = 0
o END IF
o
o rear = rear + 1
o queue[rear] = ITEM
o END ENQUEUE
 2. Dequeue (Deletion) Algorithm:
o Purpose: To remove an element from the front of the queue.
o Algorithm:
1. Check for Queue Empty (Underflow): If front == -1 or front > rear, print "Queue
Underflow" and return an error/NULL.
2. Retrieve Element: Get the element at queue[front] into a temporary variable (e.g.,
DELETED_ITEM).
3. Increment Front: Increment front by 1 (front = front + 1).
4. Handle Last Element Deleted: If front > rear after incrementing, it means the last
element has been deleted. Reset front = -1 and rear = -1 to signify an empty queue.
5. Return Element: Return DELETED_ITEM.
o Pseudocode:
o DEQUEUE(queue, front, rear)
o IF front == -1 OR front > rear THEN
o PRINT "Queue Underflow"
o RETURN ERROR_VALUE (or NULL)
o END IF
o
o DELETED_ITEM = queue[front]
o front = front + 1
o
o IF front > rear THEN // If queue becomes empty after deletion
o front = -1
o rear = -1
o END IF
o
o RETURN DELETED_ITEM
o END DEQUEUE

Here are the answers to Section C, providing detailed explanations, examples, algorithms,
and code where requested, keeping the 10-mark allocation per question in mind.

Section – C

Answer any 3 questions. Each question carries 10 marks.

(3 × 10 = 30 Marks)

22. What is a binary search tree? Explain insertion and deletion operations with an
example and diagrams.

Key Points:

 Definition: A Binary Search Tree (BST) is a node-based binary tree data structure that has
the following properties for every node:
o The value of all nodes in the left subtree is less than the value of the node.
o The value of all nodes in the right subtree is greater than the value of the node.
o Both the left and right subtrees must also be binary search trees.
o There are no duplicate nodes (though some definitions allow duplicates, placing them
typically in the right subtree).
 Importance: BSTs allow for efficient searching, insertion, and deletion operations with an
average time complexity of O(log n), making them suitable for dynamic datasets.

Insertion Operation

 Concept: To insert a new node into a BST, we traverse the tree from the root, comparing the
new node's value with current node's value to decide whether to go left or right.
 Algorithm:
1. If the tree is empty, the new node becomes the root.
2. Otherwise, start from the root.
3. Compare the ITEM to be inserted with the current_node->data:
 If ITEM < current_node->data, go to the left child.
 If ITEM > current_node->data, go to the right child.
4. Repeat step 3 until you reach a NULL child pointer.
5. Insert the new node as the left or right child of the current_node based on the last
comparison.
 Example & Diagram: Insert elements 50, 30, 70, 20, 40, 60, 80 into an empty BST.
1. Insert 50 (Root):
2. 50
3. Insert 30: (30 &lt; 50, go left, insert as left child of 50)
4. 50
5. /
6. 30
7. Insert 70: (70 > 50, go right, insert as right child of 50)
8. 50
9. / \
10. 30 70
11. Insert 20: (20 &lt; 50, go left; 20 &lt; 30, go left, insert as left child of 30)
12. 50
13. / \
14. 30 70
15. /
16. 20
17. Insert 40: (40 &lt; 50, go left; 40 > 30, go right, insert as right child of 30)
18. 50
19. / \
20. 30 70
21. / \
22. 20 40
23. Insert 60: (60 > 50, go right; 60 &lt; 70, go left, insert as left child of 70)
24. 50
25. / \
26. 30 70
27. / \ /
28. 20 40 60
29. Insert 80: (80 > 50, go right; 80 > 70, go right, insert as right child of 70)
30. 50
31. / \
32. 30 70
33. / \ / \
34. 20 40 60 80

Deletion Operation

 Concept: Deleting a node from a BST is more complex as it must maintain the BST
properties. There are three cases for deletion:
1. Case 1: Node to be deleted is a leaf node (no children).
2. Case 2: Node to be deleted has one child.
3. Case 3: Node to be deleted has two children.
 Algorithm:
1. Search for the node: First, find the node to be deleted.
2. Case 1 (No children):
 Simply remove the node. Set its parent's child pointer to NULL.
3. Case 2 (One child):
 Replace the node with its single child. Link the parent of the deleted node to the child of the
deleted node.
4. Case 3 (Two children):
 Find the inorder successor (smallest node in the right subtree) OR the inorder predecessor
(largest node in the left subtree).
 Copy the value of the inorder successor (or predecessor) to the node that needs to be deleted.
 Delete the inorder successor (or predecessor) from its original position (this deletion will be
either Case 1 or Case 2).
 Example & Diagram: Consider the BST formed above:
 50
 / \
 30 70
 / \ / \
 20 40 60 80
1. Delete 20 (Case 1: Leaf Node):
 Node 20 has no children. Set 30's left child to NULL.

<!-- end list -->


50
/ \
30 70
\ / \
40 60 80

2. Delete 70 (Case 3: Two Children):


 Node 70 has two children (60 and 80).
 Find its inorder successor: 60 (smallest in 70's right subtree).
 Copy 60's value to 70's position.
 Delete 60 (which is now a leaf node in its original position).

<!-- end list -->


50
/ \
30 60 (70 replaced by 60)
\ \
40 80 (60 removed from here)

3. Delete 30 (Case 2: One Child):


 Node 30 has one child (40).
 Replace 30 with its child 40. Link 50's left child to 40.

<!-- end list -->


50
/ \
40 60
\
80
23. Explain Breadth First Search (BFS) and Depth First Search (DFS) algorithms with
examples.

Key Points:

 Graph Traversal: Both BFS and DFS are algorithms used to explore or search a graph (or
tree). They define the order in which nodes are visited.

Breadth-First Search (BFS)

 Concept: BFS explores all the neighbor nodes at the current depth level before moving on to
the nodes at the next depth level. It uses a queue data structure to keep track of the nodes to
be visited.
 Analogy: Like ripples in a pond, expanding outwards from a central point.
 Algorithm:
1. Start by putting any one of the graph's vertices (the source) at the back of a queue.
2. Mark the source vertex as visited.
3. While the queue is not empty:
 Dequeue a vertex V.
 Visit/process V.
 Enqueue all unvisited neighbors of V and mark them as visited.
 Example: Consider the following undirected graph. Start BFS from node 'A'.
 A -- B
 | / |
 C -- D
o Vertices: {A, B, C, D}
o Edges: (A,B), (A,C), (B,C), (B,D), (C,D)

BFS Steps:

3. Initialize: Queue: [], Visited: {}.


4. Start from A: Enqueue A. Visited: {A}. Queue: [A]
5. Dequeue A: Visit A.
 Neighbors of A: B, C.
 Enqueue B. Visited: {A, B}. Queue: [C, B] (order depends on implementation, typically
alphabetical or adjacency list order)
 Enqueue C. Visited: {A, B, C}. Queue: [B, C] (if C enqueued after B)
6. Dequeue B: Visit B.
 Neighbors of B: A (visited), C (visited), D (unvisited).
 Enqueue D. Visited: {A, B, C, D}. Queue: [C, D]
7. Dequeue C: Visit C.
 Neighbors of C: A (visited), B (visited), D (visited). No unvisited neighbors. Queue: [D]
8. Dequeue D: Visit D.
 Neighbors of D: B (visited), C (visited). No unvisited neighbors. Queue: []
9. Queue is empty. BFS complete.
Traversal Order: A -> B -> C -> D (or A -> C -> B -> D depending on adjacency list order)

Depth-First Search (DFS)

 Concept: DFS explores as far as possible along each branch before backtracking. It uses a
stack data structure (or implicitly, the call stack of recursion) to keep track of the path.
 Analogy: Like navigating a maze by always going forward until a dead end, then
backtracking to the last choice point to try another path.
 Algorithm (Recursive):
1. Mark the current vertex V as visited and process it.
2. For each unvisited neighbor U of V:
 Recursively call DFS on U.
 Algorithm (Iterative using Stack):
1. Start by pushing any one of the graph's vertices (the source) onto a stack.
2. While the stack is not empty:
 Pop a vertex V from the stack.
 If V has not been visited:
 Mark V as visited and process it.
 Push all unvisited neighbors of V onto the stack (order might matter for specific traversal
paths, typically reversed to maintain order).
 Example: Consider the same undirected graph. Start DFS from node 'A'.
 A -- B
 | / |
 C -- D
o Vertices: {A, B, C, D}
o Edges: (A,B), (A,C), (B,C), (B,D), (C,D)

DFS Steps (Recursive, assuming neighbors B then C for A, etc.):

3. DFS(A):
 Visit A. Mark A visited.

 A'sneighbors: B, C.
 DFS(B):
 Visit B. Mark B visited.
 B'sneighbors: A (visited), C, D.
 DFS(C):
 Visit C. Mark C visited.
 C'sneighbors: A (visited), B (visited), D.
 DFS(D):
 Visit D. Mark D visited.
 D'sneighbors: B (visited), C (visited). No unvisited neighbors.
 Return from DFS(D).
 Return from DFS(C).
 Return from DFS(B).
 Return from DFS(A). Traversal Order: A -> B -> C -> D
24. Write a menu-driven C program to perform all stack operations using arrays.

Key Points:

 Stack Implementation: Using a fixed-size array and a top variable to keep track of the
topmost element.
 Operations:
o push(): Adds an element to the top. Checks for overflow.
o pop(): Removes and returns the top element. Checks for underflow.
o peek(): Returns the top element without removing it. Checks for underflow.
o isEmpty(): Checks if the stack is empty.
o isFull(): Checks if the stack is full.
 Menu-Driven: Provides options for the user to select desired stack operations.

C Program:
C
#include <stdio.h>
#include <stdlib.h> // For exit()

#define MAX_SIZE 5 // Define the maximum size of the stack

// Global array to store stack elements


int stack[MAX_SIZE];
// Global variable to keep track of the top of the stack
int top = -1; // Initialize top to -1 indicating an empty stack

// Function to check if the stack is empty


int isEmpty() {
return top == -1;
}

// Function to check if the stack is full


int isFull() {
return top == MAX_SIZE - 1;
}

// Function to push an element onto the stack


void push(int value) {
if (isFull()) {
printf("\nStack Overflow! Cannot push %d. Stack is full.\n",
value);
} else {
top++; // Increment top
stack[top] = value; // Add element to the new top position
printf("%d pushed to stack.\n", value);
}
}

// Function to pop an element from the stack


int pop() {
if (isEmpty()) {
printf("\nStack Underflow! Cannot pop. Stack is empty.\n");
return -1; // Return a sentinel value for error
} else {
int poppedValue = stack[top]; // Get the top element
top--; // Decrement top
printf("%d popped from stack.\n", poppedValue);
return poppedValue;
}
}

// Function to peek the top element of the stack without removing it


int peek() {
if (isEmpty()) {
printf("\nStack is empty. Cannot peek.\n");
return -1; // Return a sentinel value for error
} else {
printf("Top element is: %d\n", stack[top]);
return stack[top];
}
}

// Function to display all elements in the stack


void display() {
if (isEmpty()) {
printf("\nStack is empty. Nothing to display.\n");
} else {
printf("\nStack elements are: \n");
for (int i = top; i >= 0; i--) {
printf("%d\n", stack[i]);
}
}
}

// Main function to run the menu-driven program


int main() {
int choice, value;

while (1) { // Infinite loop for menu


printf("\n--- Stack Operations (Array Implementation) ---\n");
printf("1. Push\n");
printf("2. Pop\n");
printf("3. Peek\n");
printf("4. Check if Empty\n");
printf("5. Check if Full\n");
printf("6. Display Stack\n");
printf("7. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);

switch (choice) {
case 1:
printf("Enter value to push: ");
scanf("%d", &value);
push(value);
break;
case 2:
pop(); // No need to store return value unless needed
break;
case 3:
peek(); // No need to store return value unless needed
break;
case 4:
if (isEmpty()) {
printf("\nStack is empty.\n");
} else {
printf("\nStack is NOT empty.\n");
}
break;
case 5:
if (isFull()) {
printf("\nStack is full.\n");
} else {
printf("\nStack is NOT full.\n");
}
break;
case 6:
display();
break;
case 7:
printf("Exiting program. Goodbye!\n");
exit(0); // Exit the program
default:
printf("Invalid choice. Please try again.\n");
}
}

return 0;
}

Explain Stack using Array and Linked List with operations and code.
Stack using Array Implementation

(5 Marks)

Key Points:

1. Definition: A Stack is a linear data structure that follows the LIFO (Last-In, First-
Out) principle for insertion and deletion operations.
2. Array Representation:
o A stack can be implemented using a one-dimensional array.

o It uses a TOP variable (or pointer) to keep track of the topmost element in the stack.
Initially, TOP is often set to -1 (indicating an empty stack).
o The size of the stack is fixed when implemented with an array, meaning it can store
only a predefined number of elements.
3. Operations:
o PUSH (Insertion): Adds an element to the top of the stack.
 Algorithm:
 Step 1: Check if the stack is full (Stack Overflow condition). If TOP is equal to
MAX_SIZE - 1, the stack is full.
 Step 2: If not full, increment TOP.
 Step 3: Insert the new ITEM at the Stack[TOP] position.
 Pseudocode:
 PUSH(Stack, TOP, MAX_SIZE, ITEM)
 IF TOP == MAX_SIZE - 1 THEN
 PRINT "Stack Overflow"
 RETURN
 ELSE
 TOP = TOP + 1
 Stack[TOP] = ITEM
 END IF
 END PUSH
o POP (Deletion): Removes the topmost element from the stack.
 Algorithm:
 Step 1: Check if the stack is empty (Stack Underflow condition). If TOP is equal to -1,
the stack is empty.
 Step 2: If not empty, retrieve the element at Stack[TOP].
 Step 3: Decrement TOP.
 Pseudocode:
 POP(Stack, TOP)
 IF TOP == -1 THEN
 PRINT "Stack Underflow"
 RETURN NULL
 ELSE
 ITEM = Stack[TOP]
 TOP = TOP - 1
 RETURN ITEM
 END IF
 END POP
o PEEK/TOP: Returns the topmost element without removing it.
o ISEMPTY: Checks if the stack is empty.
o ISFULL: Checks if the stack is full (only for array implementation).
4. Advantages: Simple to implement.
5. Disadvantages: Fixed size (static), leading to potential Stack Overflow if the number
of elements exceeds the array capacity.

Stack using Linked List Implementation

(5 Marks)

Key Points:
1. Definition: A stack can be efficiently implemented using a linked list, where elements
(nodes) are dynamically allocated.
2. Linked List Representation:
o Each node in the linked list contains data and a next pointer (or link) to the next
node.
o A TOP pointer keeps track of the last inserted element (the top of the stack).
o The TOP pointer always points to the first node of the linked list (which represents
the top of the stack).
3. Operations:
o PUSH (Insertion): Inserts a new element as the top element of the stack.
 Algorithm:
 Step 1: Create a new node PTR and allocate memory for it.
 Step 2: Assign the ITEM to PTR->INFO.
 Step 3: Set PTR->LINK = TOP.
 Step 4: Update TOP = PTR.
 Pseudocode:
 PUSH(TOP, ITEM)
 PTR = new Node()
 PTR->INFO = ITEM
 PTR->LINK = TOP
 TOP = PTR
 END PUSH
o POP (Deletion): Removes the topmost node from the stack (the node pointed to by
TOP).
 Algorithm:
 Step 1: Check if the stack is empty (Stack Underflow condition). If TOP is NULL, the
stack is empty.
 Step 2: If not empty, store the INFO of the TOP node into a temporary variable N.
 Step 3: Move TOP to TOP->LINK.
 Step 4: Free the memory of the original TOP node.
 Pseudocode:
 POP(TOP)
 IF TOP == NULL THEN
 PRINT "Stack is Empty (Underflow)"
 RETURN NULL
 ELSE
 N = TOP->INFO
 TEMP = TOP
 TOP = TOP->LINK
 FREE(TEMP)
 RETURN N
 END IF
 END POP
o PEEK/TOP: Returns the data of the TOP node without removing it.
o ISEMPTY: Checks if TOP is NULL.
4. Advantages:
o Dynamic size: The stack can grow or shrink as needed, avoiding the "Stack Overflow"
issue due to fixed capacity.
o Efficient memory utilization.
5. Disadvantages:
o Requires more memory per element (due to storing pointers).

o Slightly more complex to implement than array-based stacks.

You might also like