Chapter 4
Data Structures and Algorithms
TU BSc CSIT past exam questions
Past questions and answers
84 questions set from this chapter. Most repeated first.
- 2080 · 5 marks
How can you use linked list to implement stack? Explain.
Similar questions: Define list. How can you use linked (2081)
Answer
A stack follows LIFO, so with a singly linked list the head of the list is used as the top of the stack. Inserting and deleting at the head takes time, and the stack grows and shrinks dynamically, so there is no fixed-size overflow.
struct node {
int data;
struct node *next;
};
struct node *top = NULL;
Push(x):
- Allocate a new node
nand setn->data = x. - Set
n->next = top(link it to the current top). - Set
top = n.
void push(int x) {
struct node *n = (struct node *)malloc(sizeof(struct node));
if (n == NULL) { printf("Overflow\n"); return; }
n->data = x;
n->next = top;
top = n;
}
Pop():
- If
top == NULL, the stack is empty (underflow). - Otherwise save
t = top, settop = top->next, readx = t->data,free(t)and returnx.
int pop() {
if (top == NULL) { printf("Underflow\n"); return -1; }
struct node *t = top;
int x = t->data;
top = top->next;
free(t);
return x;
}
Example: push 10, 20, 30 gives top -> 30 -> 20 -> 10 -> NULL. A pop returns 30 and leaves top -> 20 -> 10. The stack is empty when top == NULL. Memory is used only for stored items, at the cost of an extra pointer per element.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 10 marks
Define list. How can you use linked list to implement stack? Explain circular linked list.
Similar questions: How can you use linked list to (2080)
Answer
List. A list is a finite, ordered collection of elements of the same type in which every element has a position (first, second, ... last). Typical operations are insert, delete, search, traverse and count. A list can be stored contiguously in an array (static, fixed size) or as a linked list, in which each element is a node holding the data and a pointer to the next node, so the list can grow and shrink at run time.
struct node {
int data;
struct node *next;
};
Implementing a stack with a linked list. A stack is a LIFO structure: insertion (push) and deletion (pop) take place only at one end, the top. In a linked list, inserting and deleting at the head (front) takes time, so the head of the list is used as the top of the stack. The pointer top points to the first node; an empty stack has top = NULL. There is no overflow except when memory is exhausted, and no space is wasted by a fixed array size.
PUSH(x):
- Create a new node
p; if memory is not available, report overflow. p->data = xp->next = toptop = p
POP:
- If
top == NULL, report underflow and stop. p = top;x = p->datatop = top->nextfree(p); returnx
void push(int x) {
struct node *p = (struct node*)malloc(sizeof(struct node));
if (p == NULL) { printf("Overflow\n"); return; }
p->data = x;
p->next = top;
top = p;
}
int pop(void) {
if (top == NULL) { printf("Underflow\n"); return -1; }
struct node *p = top;
int x = p->data;
top = top->next;
free(p);
return x;
}
Both operations are . For example, pushing 10, 20, 30 gives top -> 30 -> 20 -> 10 -> NULL; a pop returns 30 and top then points to 20.
Circular linked list. In a circular linked list the next pointer of the last node points back to the first node instead of NULL, so the nodes form a ring and there is no node with a NULL link. It may be singly circular (each node has next only) or doubly circular (next and prev, with the last node's next pointing to the first and the first node's prev pointing to the last).
external pointer
|
v
[10|*]-->[20|*]-->[30|*]
^ |
|__________________|
Features and advantages:
- Any node can be reached from any other node, since traversal can start anywhere and continues round the ring.
- It is convenient to keep a pointer
lastto the last node; then the first node islast->next, so insertion at both the front and the end takes time. - It is suitable for round-robin CPU scheduling, a ring of players in a game, and implementing circular queues.
- Traversal must stop when we return to the starting node (
p->next == start) instead of testing forNULL, otherwise it loops forever.
Insertion at the front of a circular list with last pointer:
void insert_front(int x) {
struct node *p = (struct node*)malloc(sizeof(struct node));
p->data = x;
if (last == NULL) { /* empty list */
last = p;
p->next = p;
} else {
p->next = last->next;
last->next = p;
}
}
Traversal:
void display(void) {
if (last == NULL) return;
struct node *p = last->next;
do {
printf("%d ", p->data);
p = p->next;
} while (p != last->next);
}
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 10 marks
Illustrate the algorithm for Binary search tree with example.
Answer
A binary search tree (BST) is a binary tree in which, for every node, all keys in the left subtree are smaller than the node's key and all keys in the right subtree are larger (duplicates are not allowed or are handled by a fixed rule). An inorder traversal of a BST gives the keys in sorted order.
Node structure
struct node {
int info;
struct node *left, *right;
};
Insertion algorithm
- If the tree is empty, make the new node the root.
- Otherwise compare the key with the current node. If key info, go left; if key info, go right.
- Repeat until a NULL link is found and attach the new node there.
struct node* insert(struct node *root, int key) {
if (root == NULL) {
struct node *p = (struct node*)malloc(sizeof(struct node));
p->info = key; p->left = p->right = NULL;
return p;
}
if (key < root->info) root->left = insert(root->left, key);
else if (key > root->info) root->right = insert(root->right, key);
return root;
}
Search algorithm
struct node* search(struct node *root, int key) {
if (root == NULL || root->info == key) return root;
if (key < root->info) return search(root->left, key);
return search(root->right, key);
}
Deletion has three cases:
- Node is a leaf: remove it.
- Node has one child: replace the node by its child.
- Node has two children: replace its key by the inorder successor (smallest key in the right subtree) or inorder predecessor, then delete that node.
struct node* delete(struct node *root, int key) {
if (root == NULL) return NULL;
if (key < root->info) root->left = delete(root->left, key);
else if (key > root->info) root->right = delete(root->right, key);
else {
if (root->left == NULL) { struct node *t = root->right; free(root); return t; }
if (root->right == NULL) { struct node *t = root->left; free(root); return t; }
struct node *s = root->right;
while (s->left != NULL) s = s->left;
root->info = s->info;
root->right = delete(root->right, s->info);
}
return root;
}
Example. Insert the keys 50, 30, 70, 20, 40, 60, 80 in this order.
- 50 becomes the root.
- 30 50: left child of 50.
- 70 50: right child of 50.
- 20 50, 30: left child of 30.
- 40 50, 30: right child of 30.
- 60 50, 70: left child of 70.
- 80 50, 70: right child of 70.
50
/ \
30 70
/ \ / \
20 40 60 80
Searching for 60: compare with 50 (go right), with 70 (go left), found 60 after 3 comparisons. Inorder traversal gives 20, 30, 40, 50, 60, 70, 80 (sorted). Deleting 30 (two children) replaces it with its inorder successor 40, leaving 40 with left child 20.
Complexity. Search, insert and delete take where is the height: for a balanced tree and in the worst case (a skewed tree from sorted input).
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 10 marks
What do you mean by circular list? Differentiate between stack as a circular list and Queue as a circular list.
Answer
Circular list. A circular list is a linked list in which the last node points back to the first node instead of NULL, so the list forms a ring. Any node can be reached from any other node, and there is no NULL pointer. It may be singly or doubly linked. A single external pointer to the last node gives access to both ends: last->next is the first node.
Stack as a circular list. A stack needs access to only one end (the top). Using a circular list, a single external pointer top/last is kept, and last->next is the top node.
- Push: new node is inserted after
last(at the front of the list), solast->nextalways refers to the top; the last node's link is updated. - Pop: the node after
lastis deleted. - Both operations are done at the same end, in time. Order is LIFO.
Queue as a circular list. A queue needs access to both ends. With one pointer rear pointing to the last node, rear->next is the front.
- Insert (enqueue): a new node is placed after
rearandrearis moved to it. - Delete (dequeue): the node
rear->next(front) is removed. - Insertion at the rear and deletion at the front, both . Order is FIFO.
| Basis | Stack as circular list | Queue as circular list |
|---|---|---|
| Order | LIFO | FIFO |
| Insertion | At the front, after last | At the rear, after rear, and rear moves forward |
| Deletion | From the front (same end as insertion) | From the front (opposite end from insertion) |
| Pointer moves | The external pointer stays on the last node (except when the stack becomes empty or has one node) | rear moves on every insertion |
| Ends used | One end only | Both ends |
| Empty condition | last == NULL | rear == NULL |
| Overflow | Only when memory is exhausted | Only when memory is exhausted |
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 10 marks
Explain the procedure for construction of Huffman algorithm with example.
Answer
Huffman algorithm is a greedy algorithm that builds an optimal prefix code (variable-length binary codes, no code is a prefix of another) for data compression. Frequent symbols get short codes and rare symbols get long codes.
Procedure
- Create a leaf node for each symbol with its frequency, and put all nodes in a priority queue (min-heap) ordered by frequency.
- Remove the two nodes with the smallest frequencies.
- Create a new internal node whose frequency is their sum, with these two nodes as children, and insert it back into the queue.
- Repeat steps 2 and 3 until only one node remains. It is the root of the Huffman tree.
- Label every left edge 0 and every right edge 1. The code of a symbol is the sequence of labels from the root to its leaf.
Example. Symbols and frequencies: A = 5, B = 9, C = 12, D = 13, E = 16, F = 45 (total 100).
- Merge A(5) and B(9) to get N1 = 14.
- Merge C(12) and D(13) to get N2 = 25.
- Merge N1(14) and E(16) to get N3 = 30.
- Merge N2(25) and N3(30) to get N4 = 55.
- Merge F(45) and N4(55) to get root = 100.
100
/ \
F(45) 55
/ \
25 30
/ \ / \
C(12) D(13) 14 E(16)
/ \
A(5) B(9)
With left = 0 and right = 1:
| Symbol | Frequency | Code | Length |
|---|---|---|---|
| F | 45 | 0 | 1 |
| C | 12 | 100 | 3 |
| D | 13 | 101 | 3 |
| A | 5 | 1100 | 4 |
| B | 9 | 1101 | 4 |
| E | 16 | 111 | 3 |
Total bits .
A fixed 3-bit code would need bits, so Huffman coding saves bits ().
Decoding is done by reading bits from the root: go left on 0, right on 1, output the symbol on reaching a leaf and restart. With a heap, building the tree takes .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
Differentiate between structure and union.
Answer
| Basis | Structure | Union |
|---|---|---|
| Keyword | struct | union |
| Memory | Each member gets its own separate memory; size is at least the sum of the member sizes (plus padding) | All members share the same memory; size equals the size of the largest member |
| Access | All members can be used at the same time | Only one member holds a valid value at a time; writing one overwrites the others |
| Value storage | Each member keeps its own value | The last stored value only |
| Use | To group related data of different types (records) | To save memory when only one of several alternatives is needed at a time |
| Initialisation | Any/all members can be initialised | Only the first member can be initialised at declaration |
struct S { int a; float b; char c; }; // size about 4+4+1 (+padding) = 12 bytes
union U { int a; float b; char c; }; // size 4 bytes
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
Describe the Big ‘O’ notation.
Answer
Big O notation gives an asymptotic upper bound on the growth rate of an algorithm's running time (or space) as the input size becomes large. It describes the worst-case order of growth and ignores constants and lower-order terms.
Definition. if there exist positive constants and such that
Example. For : since for all , we have , , so . Similarly .
Common orders (slowest growth to fastest):
Examples: array access , binary search , linear search , merge sort , bubble sort .
Big O is used to compare algorithms independently of the machine and language.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
Explain the infix to post fix conversion algorithm.
Answer
Infix expressions (operator between operands, e.g. ) need precedence and parenthesis rules. Postfix expressions (operator after operands, ) do not, so conversion uses a stack to hold operators.
Precedence: ^ (highest, right-associative), then * /, then + -. Parentheses override precedence.
Algorithm
- Scan the infix expression from left to right.
- If the symbol is an operand, append it to the postfix output.
- If it is
(, push it on the stack. - If it is
), pop operators from the stack to the output until(is found; discard both parentheses. - If it is an operator, pop operators from the stack to the output while the top has higher precedence than the scanned operator (or equal precedence for left-associative operators); then push the scanned operator.
- After the scan ends, pop all remaining operators to the output.
Example. Convert .
| Symbol | Stack | Postfix |
|---|---|---|
| A | A | |
| + | + | A |
| B | + | AB |
| * | + * | AB |
| C | + * | ABC |
| - | - (pop *, then + ; push -) | ABC*+ |
| D | - | ABC*+D |
| end | ABC*+D- |
Result: . The algorithm runs in time.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
Explain the Tower of Hanoi (TOH) with practical example.
Answer
The Tower of Hanoi is a classic recursive puzzle. There are three pegs (source A, auxiliary B, destination C) and disks of different sizes stacked on A with the largest at the bottom. The task is to move all disks to C obeying two rules: move only one disk at a time, and never place a larger disk on a smaller one.
Recursive idea
To move disks from A to C using B:
- Move the top disks from A to B (using C).
- Move the largest disk from A to C.
- Move the disks from B to C (using A).
void toh(int n, char from, char to, char aux) {
if (n == 0) return;
toh(n-1, from, aux, to);
printf("Move disk %d from %c to %c\n", n, from, to);
toh(n-1, aux, to, from);
}
Example, (A to C using B), 7 moves:
- Disk 1: A to C
- Disk 2: A to B
- Disk 1: C to B
- Disk 3: A to C
- Disk 1: B to A
- Disk 2: B to C
- Disk 1: A to C
Number of moves. , , giving For : . The time complexity is . A practical use is the stack-based nature of recursion, and it is a standard demonstration of how recursion simplifies a problem.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
What do you mean by double linked list? Explain with example.
Answer
A doubly linked list is a linked list in which each node has two pointers: one to the next node and one to the previous node. It can be traversed in both directions.
struct node {
int info;
struct node *prev;
struct node *next;
};
NULL <- [prev|10|next] <-> [prev|20|next] <-> [prev|30|next] -> NULL
Advantages: traversal in both directions; a node can be deleted given only a pointer to it (no need to track the previous node); easy insertion before a node. Disadvantages: extra memory for the second pointer; more pointer updates for each operation.
Example: insert a new node p after node q.
p->prev = q;
p->next = q->next;
if (q->next != NULL)
q->next->prev = p;
q->next = p;
Example: delete node q.
if (q->prev != NULL) q->prev->next = q->next;
if (q->next != NULL) q->next->prev = q->prev;
free(q);
If the list holds 10, 20, 30 and 25 is inserted after 20, the list becomes 10 <-> 20 <-> 25 <-> 30. Both insertion and deletion at a known position take .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
What are the types of binary tree? Compare between them.
Answer
A binary tree is a tree in which each node has at most two children (left and right). The main types are:
- Strictly (full) binary tree: every node has either 0 or 2 children. A strictly binary tree with leaves has nodes.
- Complete binary tree: all levels are completely filled except possibly the last, and the last level is filled from left to right. Heaps are complete trees.
- Perfect binary tree: all internal nodes have two children and all leaves are at the same level. It has nodes for height .
- Skewed binary tree: every node has only a left child (left-skewed) or only a right child (right-skewed); behaves like a linked list.
- Binary search tree: left subtree keys node right subtree keys.
- Balanced tree (AVL): for every node the heights of the left and right subtrees differ by at most 1.
- Expression tree: leaves are operands and internal nodes are operators.
Comparison
| Type | Nodes with children | Shape | Height for nodes |
|---|---|---|---|
| Strictly binary | 0 or 2 | Not necessarily level-filled | between and |
| Complete | Filled left to right | Last level may be partial | |
| Perfect | All internal nodes have 2 | All leaves at same level | |
| Skewed | Every node has 1 (except the last) | Like a list | |
| BST | Any | Ordered by key | to |
| AVL | Any | Height-balanced |
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
Differentiate between pre-order traversal and in order traversal.
Answer
Both are depth-first traversals of a binary tree, defined recursively. They differ in when the root (current node) is visited.
| Basis | Preorder | Inorder |
|---|---|---|
| Order | Root, Left, Right (NLR) | Left, Root, Right (LNR) |
| Root visited | First | Between the left and right subtrees |
| First node output | The root of the tree | The leftmost node |
| Result on a BST | Not sorted | Keys in ascending sorted order |
| Uses | Copying a tree, prefix expression of an expression tree | Sorted output of a BST, infix expression |
| Reconstruction | Needs inorder also to build a unique tree | Needs preorder or postorder also |
Example tree:
A
/ \
B C
/ \
D E
- Preorder: A B D E C
- Inorder: D B E A C
void preorder(struct node *t) { if (t) { printf("%d ", t->info); preorder(t->left); preorder(t->right); } }
void inorder(struct node *t) { if (t) { inorder(t->left); printf("%d ", t->info); inorder(t->right); } }
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
What do you mean by sorting? Explain the Bubble sort with example.
Answer
Sorting is the process of arranging the elements of a list in a specified order, ascending or descending (numerically or alphabetically). Sorting makes searching and processing data faster.
Bubble sort. It repeatedly compares adjacent elements and swaps them if they are in the wrong order. After each pass the largest remaining element "bubbles" to its final position at the end. For elements, passes are needed; pass compares the first pairs. If a pass makes no swap, the list is sorted and the algorithm can stop.
void bubble(int a[], int n) {
for (int i = 0; i < n-1; i++) {
int swapped = 0;
for (int j = 0; j < n-1-i; j++)
if (a[j] > a[j+1]) {
int t = a[j]; a[j] = a[j+1]; a[j+1] = t;
swapped = 1;
}
if (!swapped) break;
}
}
Example. Sort 5, 1, 4, 2, 8.
- Pass 1: (5,1) swap: 1 5 4 2 8; (5,4) swap: 1 4 5 2 8; (5,2) swap: 1 4 2 5 8; (5,8) no swap. Result 1 4 2 5 8.
- Pass 2: (1,4) no; (4,2) swap: 1 2 4 5 8; (4,5) no. Result 1 2 4 5 8.
- Pass 3: no swaps, so the list is sorted: 1 2 4 5 8.
Complexity. Worst and average case (about comparisons); best case with the swap flag; space ; it is stable.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
Differentiate between sequential searching and binary searching.
Answer
| Basis | Sequential (linear) search | Binary search |
|---|---|---|
| Method | Compares the key with each element one by one from the start | Repeatedly compares the key with the middle element and discards half of the list |
| Data order | Works on sorted or unsorted data | Requires sorted data |
| Data structure | Arrays and linked lists | Needs random access, so arrays (not suitable for linked lists) |
| Best case | ||
| Average/worst case | ||
| Speed for large data | Slow | Very fast; 1,000,000 items need at most about 20 comparisons |
| Implementation | Very simple | More complex |
| Suitable for | Small or unsorted lists | Large sorted lists |
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2074 · 5 marks
Discuss the Kruskal’s algorithm with example.
Answer
Kruskal's algorithm finds a minimum spanning tree (MST) of a connected, weighted, undirected graph using the greedy approach: it repeatedly adds the cheapest edge that does not form a cycle.
Algorithm
- Sort all edges in non-decreasing order of weight.
- Start with a forest in which each vertex is its own component.
- Take the next smallest edge. If its end points lie in different components, add it to the MST and merge the components (checked with union-find); otherwise discard it, since it would form a cycle.
- Stop when edges have been selected.
With sorting, the time complexity is .
Example. Vertices A, B, C, D, E with edges: B-C = 1, A-C = 2, D-E = 2, A-B = 4, B-D = 5, C-D = 8, C-E = 10.
| Edge | Weight | Decision |
|---|---|---|
| B-C | 1 | Accept |
| A-C | 2 | Accept |
| D-E | 2 | Accept |
| A-B | 4 | Reject (A and B already connected through C) |
| B-D | 5 | Accept (joins {A,B,C} with {D,E}) |
Four edges () are selected, so the algorithm stops. MST edges: B-C, A-C, D-E, B-D with total weight .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 10 marks
How can you use stack to convert an infix expression to postfix? Convert infix expression (A + B)*(C – D) to postfix using stack.
Answer
Infix notation places the operator between its operands and needs precedence and parenthesis rules. Postfix notation places the operator after its operands and needs neither. A stack is used to hold operators (and parentheses) until their operands have been output, which reverses the order of operators according to precedence.
Algorithm
- Scan the infix expression from left to right.
- If the symbol is an operand, send it directly to the postfix output.
- If it is
(, push it on the stack. - If it is
), pop operators to the output until(is on top; pop and discard(. - If it is an operator, while the stack top is an operator of higher or equal precedence (for left-associative operators), pop it to the output; then push the scanned operator.
- At the end of the expression, pop all remaining operators to the output.
Precedence: ^ *, / +, -; ( has the lowest precedence while on the stack.
Conversion of
| Step | Symbol | Stack (bottom to top) | Postfix output |
|---|---|---|---|
| 1 | ( | ( | |
| 2 | A | ( | A |
| 3 | + | ( + | A |
| 4 | B | ( + | AB |
| 5 | ) | (empty) | AB+ |
| 6 | * | * | AB+ |
| 7 | ( | * ( | AB+ |
| 8 | C | * ( | AB+C |
| 9 | - | * ( - | AB+C |
| 10 | D | * ( - | AB+CD |
| 11 | ) | * | AB+CD- |
| 12 | end | (empty) | AB+CD-* |
The postfix expression is .
Check by evaluation. Let . Infix: . Postfix: push 2, 3; + gives 5; push 7, 4; - gives 3; * gives .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 10 marks
Explain concept of divide and conquer algorithm. Hand test quick algorithm with array of numbers (78, 34, 21, 43, 7, 18, 9, 56, 38, 19).sorting What is time complexity of quick sort algorithm?
Answer
Divide and conquer. It is an algorithm design technique that solves a problem in three steps:
- Divide the problem into smaller sub-problems of the same type.
- Conquer the sub-problems by solving them recursively (solve directly when small enough).
- Combine the solutions of the sub-problems to get the solution of the original problem.
Examples: merge sort, quick sort, binary search, Strassen's matrix multiplication.
Quick sort. Choose a pivot element, partition the array so that elements smaller than the pivot are on its left and larger elements on its right (the pivot is then in its final position), and sort the two parts recursively. The combine step is trivial.
void quick(int a[], int lo, int hi) {
if (lo >= hi) return;
int p = a[lo], i = lo + 1, j = hi;
while (1) {
while (i <= hi && a[i] <= p) i++;
while (a[j] > p) j--;
if (i >= j) break;
int t = a[i]; a[i] = a[j]; a[j] = t;
}
a[lo] = a[j]; a[j] = p;
quick(a, lo, j-1);
quick(a, j+1, hi);
}
Hand test on 78, 34, 21, 43, 7, 18, 9, 56, 38, 19 (first element as pivot). Each partition places the pivot in its final position:
| Sub-array | Pivot | Left part | Right part |
|---|---|---|---|
| 78 34 21 43 7 18 9 56 38 19 | 78 | 34 21 43 7 18 9 56 38 19 (all smaller) | empty |
| 34 21 43 7 18 9 56 38 19 | 34 | 21 7 18 9 19 | 43 56 38 |
| 21 7 18 9 19 | 21 | 7 18 9 19 | empty |
| 7 18 9 19 | 7 | empty | 18 9 19 |
| 18 9 19 | 18 | 9 | 19 |
| 43 56 38 | 43 | 38 | 56 |
Combining the pivots and single elements in order gives the sorted array:
7, 9, 18, 19, 21, 34, 38, 43, 56, 78
Time complexity of quick sort
- Best case (pivot splits the array into equal halves): , giving .
- Average case: .
- Worst case (already sorted or reverse-sorted input with first/last pivot, as at the first step above): , giving .
- Space: on average for the recursion stack.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 10 marks
Discuss depth first and breadth first traversal of a graph with suitable example.
Answer
Graph traversal visits every vertex reachable from a start vertex exactly once. The two standard methods are depth first search (DFS) and breadth first search (BFS).
Depth first traversal (DFS)
DFS goes as deep as possible along a path before backtracking. It uses a stack (or recursion).
- Visit the start vertex, mark it visited and push it.
- While the stack is not empty, look at the top vertex; if it has an unvisited neighbour, visit it, mark it and push it; otherwise pop the top vertex (backtrack).
void dfs(int v) {
visited[v] = 1; printf("%d ", v);
for (int w = 0; w < n; w++)
if (adj[v][w] && !visited[w]) dfs(w);
}
Breadth first traversal (BFS)
BFS visits all neighbours of a vertex before moving to the next level. It uses a queue.
- Visit the start vertex, mark it and enqueue it.
- While the queue is not empty, dequeue a vertex and enqueue all its unvisited neighbours (marking them visited as they are visited).
void bfs(int s) {
int q[MAX], f = 0, r = 0;
visited[s] = 1; q[r++] = s;
while (f < r) {
int v = q[f++]; printf("%d ", v);
for (int w = 0; w < n; w++)
if (adj[v][w] && !visited[w]) { visited[w] = 1; q[r++] = w; }
}
}
Example. Graph with edges A-B, A-C, B-D, B-E, C-F, E-F. Adjacency lists (alphabetical order): A: B, C; B: A, D, E; C: A, F; D: B; E: B, F; F: C, E.
DFS from A: visit A, go to B, then D (dead end, backtrack to B), then E, then F, then C. DFS order: A B D E F C.
BFS from A: queue A; dequeue A and add B, C; dequeue B and add D, E; dequeue C and add F; then D, E, F have no new neighbours. BFS order: A B C D E F.
Complexity. Both take with adjacency lists and with an adjacency matrix. DFS is used for cycle detection, topological sorting and connected components; BFS for shortest paths in unweighted graphs.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 5 marks
What do you mean by complexity of algorithms? How do you find time complexity?
Answer
Complexity of an algorithm. The complexity of an algorithm measures the resources it needs as a function of the input size . There are two kinds:
- Time complexity: the amount of time (number of basic operations) the algorithm takes.
- Space complexity: the amount of memory the algorithm uses, including input, auxiliary variables and recursion stack.
It is usually expressed in asymptotic notation: Big O (upper bound), Omega (lower bound) and Theta (tight bound), and analysed for the best, average and worst cases.
Finding time complexity
- Choose the basic operation (comparison, assignment, arithmetic) and the input size .
- Count how many times it executes as a function of .
- Keep the dominant term and drop constants and lower-order terms.
Rules:
- A simple statement costs .
- A sequence of statements: add the costs, so the maximum dominates.
- A loop: (cost of the body) (number of iterations).
- Nested loops: multiply the iteration counts.
- A loop where the counter doubles or halves each time runs times.
- A recursive algorithm gives a recurrence, e.g. , solved by substitution or the master theorem, giving .
Examples
for (i = 0; i < n; i++) // n times
sum += i; // O(n)
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) // n * n times
count++; // O(n^2)
for (i = 1; i < n; i *= 2) // log2 n times
x++; // O(log n)
For the nested loops the operation count is , so . For a loop with a body that runs times, .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 5 marks
Compare stack with queue. How is linear queue different from circular queue?
Answer
Stack vs queue
| Basis | Stack | Queue |
|---|---|---|
| Principle | LIFO (last in, first out) | FIFO (first in, first out) |
| Ends used | One end, the top | Two ends: rear for insertion, front for deletion |
| Insert operation | push | enqueue / insert |
| Delete operation | pop | dequeue / delete |
| Pointers | One pointer top | Two pointers front and rear |
| Applications | Recursion, expression evaluation, undo, parenthesis matching | Scheduling, buffering, BFS, printer spooling |
Linear queue vs circular queue
| Basis | Linear queue | Circular queue |
|---|---|---|
| Structure | Elements are in a straight line; rear only moves forward | The last position is connected to the first position |
| Memory use | Space freed at the front by deletions is never reused, so the queue may show "full" (rear == MAX-1) even if empty slots exist at the front | Freed slots are reused by wrapping around |
| Full condition | rear == MAX-1 | (rear+1) % MAX == front |
| Rear update | rear = rear + 1 | rear = (rear + 1) % MAX |
| Efficiency | Wasteful | Better utilisation of the array |
| Implementation | Simpler | Slightly more complex |
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 5 marks
What is ADT? Discuss stack as an ADT.
Answer
Abstract data type (ADT). An ADT is a mathematical model of a data structure that specifies the data it holds and the operations that can be done on it, together with their behaviour, without saying how they are implemented. The user works only through the interface (information hiding). The same ADT can be implemented with arrays or linked lists. Examples: stack, queue, list, tree.
Stack as an ADT
Data: an ordered collection of elements of one type, with insertion and deletion allowed only at one end, the top. It follows the LIFO principle.
Operations:
| Operation | Description |
|---|---|
create() / init() | Make an empty stack |
push(x) | Insert element at the top; error (overflow) if the stack is full |
pop() | Remove and return the top element; error (underflow) if empty |
peek() / top() | Return the top element without removing it |
isEmpty() | True if the stack has no element |
isFull() | True if no more elements can be pushed (array implementation) |
Axioms: pop(push(S, x)) = S, and peek(push(S, x)) = x.
#define MAX 100
struct stack { int items[MAX]; int top; }; // top = -1 means empty
void push(struct stack *s, int x) {
if (s->top == MAX-1) printf("Overflow\n");
else s->items[++s->top] = x;
}
int pop(struct stack *s) {
if (s->top == -1) { printf("Underflow\n"); return -1; }
return s->items[s->top--];
}
All operations take time. Applications include function calls, expression conversion and evaluation, and undo operations.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 5 marks
Define recursive algorithm? How do you implement recursive algorithms while writing computer programs?
Answer
Recursive algorithm. A recursive algorithm is one that solves a problem by calling itself on smaller instances of the same problem. It must have:
- A base case (stopping condition) that is solved directly.
- A recursive case that reduces the problem towards the base case.
Examples: factorial, Fibonacci numbers, Tower of Hanoi, tree traversal.
Implementation in programs. A recursive algorithm is written as a function that calls itself. Each call creates a new activation record (parameters, local variables, return address) on the system call stack. When the base case is reached, calls return one by one, in the reverse order (LIFO).
int fact(int n) {
if (n == 0) return 1; // base case
return n * fact(n - 1); // recursive case
}
Trace of fact(3): fact(3) calls fact(2), which calls fact(1), which calls fact(0) returning 1. Then fact(1) = 1, fact(2) = 2, fact(3) = 6.
Fibonacci:
int fib(int n) {
if (n <= 1) return n;
return fib(n-1) + fib(n-2);
}
Points to remember. Without a reachable base case the recursion never ends (stack overflow). Recursion gives short and clear code but uses extra stack space and function-call overhead; any recursive algorithm can be converted to an iterative one using an explicit stack.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 5 marks
What are the benefits of using linked list over array? How can you insert a node in a singly linked list?
Answer
Benefits of a linked list over an array
| Basis | Linked list | Array |
|---|---|---|
| Size | Dynamic, grows and shrinks at run time | Fixed at declaration |
| Memory | Allocated when needed, no waste | May be wasted or insufficient |
| Insertion/deletion | once the position is known; no shifting of elements | because elements must be shifted |
| Memory layout | Nodes need not be contiguous | Needs one contiguous block |
| Expansion | Easy | Needs reallocation and copying |
Drawbacks: extra memory for pointers and no direct (random) access, so access to the -th element is .
Inserting a node in a singly linked list
struct node { int info; struct node *next; };
(a) At the beginning:
p = (struct node*)malloc(sizeof(struct node));
p->info = x;
p->next = head;
head = p;
(b) At the end:
p->info = x; p->next = NULL;
if (head == NULL) head = p;
else {
q = head;
while (q->next != NULL) q = q->next;
q->next = p;
}
(c) After a given node q:
p->info = x;
p->next = q->next;
q->next = p;
The order of the last two statements matters: set p->next first, otherwise the rest of the list is lost. Insertion at the beginning or after a given node takes ; at the end it takes (without a tail pointer).
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 5 marks
How do you implement binary search algorithm? What is time complexity of this algorithm?
Answer
Binary search. It finds a key in a sorted array by repeatedly comparing the key with the middle element:
- Set
low = 0,high = n-1. - While
low <= high: computemid = (low + high) / 2. - If
a[mid] == key, the search is successful; returnmid. - If
key < a[mid], sethigh = mid - 1; otherwise setlow = mid + 1. - If the loop ends, the key is not present.
int binsearch(int a[], int n, int key) {
int low = 0, high = n - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (a[mid] == key) return mid;
else if (key < a[mid]) high = mid - 1;
else low = mid + 1;
}
return -1;
}
A recursive version calls binsearch(a, low, mid-1, key) or binsearch(a, mid+1, high, key).
Example. Search 23 in 2, 5, 8, 12, 16, 23, 38, 56 (indices 0 to 7): mid = 3 (12), 23 12 so low = 4; mid = 5 (23), found at index 5.
Time complexity. Each step halves the search range, so the recurrence is , which gives in the worst and average case, and in the best case (key at the middle). Space is for the iterative version.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 5 marks
What is hashing? Discuss rehashing with example.
Answer
Hashing. Hashing is a technique for storing and searching data in nearly constant time. A hash function maps a key to an index of a hash table, e.g. for table size . When two keys map to the same index, a collision occurs; it is resolved by chaining (linked list at each slot) or open addressing (linear probing, quadratic probing, double hashing). Search, insert and delete take on average.
Rehashing. In open addressing, as the table fills, the load factor (number of keys / table size) grows, collisions increase and performance falls; insertion may even fail. Rehashing builds a new, larger table (usually about twice the size, rounded up to a prime number), a new hash function with the new size is used, and every existing key is reinserted into the new table. It is done when exceeds a threshold (such as 0.7) or when an insertion fails. Its cost is but it happens rarely, so the amortised cost of an insertion stays .
Example. Table size , , linear probing. Insert 13, 15, 6, 24, 23.
- 13 mod 7 = 6, so index 6.
- 15 mod 7 = 1, so index 1.
- 6 mod 7 = 6, occupied, so next free index is 0 (wraps around).
- 24 mod 7 = 3, so index 3.
- 23 mod 7 = 2, so index 2.
| Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|---|
| Key | 6 | 15 | 23 | 24 | 13 |
Load factor , so rehash. New size = next prime after , that is 17, with . Reinsert the keys in old table order 6, 15, 23, 24, 13:
- 6 mod 17 = 6, index 6.
- 15 mod 17 = 15, index 15.
- 23 mod 17 = 6, occupied, so index 7.
- 24 mod 17 = 7, occupied, so index 8.
- 13 mod 17 = 13, index 13.
| Index | 6 | 7 | 8 | 13 | 15 |
|---|---|---|---|---|---|
| Key | 6 | 23 | 24 | 13 | 15 |
Load factor falls to , so collisions are reduced.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 5 marks
How do you transverse a binary tree? Discuss.
Answer
Traversing a binary tree means visiting every node exactly once in some systematic order. Since a tree is not linear, there are several orders. Each is defined recursively in terms of N (visit the node), L (traverse the left subtree) and R (traverse the right subtree).
1. Preorder (N L R): visit the root, traverse the left subtree in preorder, then the right subtree in preorder.
2. Inorder (L N R): traverse the left subtree, visit the root, then traverse the right subtree. For a binary search tree this gives the keys in sorted order.
3. Postorder (L R N): traverse the left subtree, the right subtree, then visit the root.
4. Level order: visit nodes level by level from left to right, using a queue.
void preorder(struct node *t) { if (t) { printf("%d ", t->info); preorder(t->left); preorder(t->right); } }
void inorder(struct node *t) { if (t) { inorder(t->left); printf("%d ", t->info); inorder(t->right); } }
void postorder(struct node *t) { if (t) { postorder(t->left); postorder(t->right); printf("%d ", t->info); } }
Example
A
/ \
B C
/ \ \
D E F
- Preorder: A B D E C F
- Inorder: D B E A C F
- Postorder: D E B F C A
- Level order: A B C D E F
Each traversal visits every node once, so the time is ; the recursion stack needs space, where is the tree height. Preorder is used to copy a tree, inorder to get sorted output, and postorder to delete a tree or evaluate an expression tree.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2075 · 5 marks
Write short notes on:
- Dynamic memory allocation
- Game tree
Answer
(a) Dynamic memory allocation
Dynamic memory allocation is the process of requesting memory from the heap at run time, when the program actually needs it, instead of fixing the size at compile time. The memory can be released when it is no longer needed, so the program uses only as much memory as the data requires.
In C, the functions of <stdlib.h> are used:
malloc(size)allocatessizebytes (uninitialised) and returns avoid *.calloc(n, size)allocatesnblocks and initialises them to zero.realloc(ptr, newsize)resizes a previously allocated block.free(ptr)returns the block to the heap.
int *a = (int *)malloc(n * sizeof(int));
if (a == NULL) { /* allocation failed */ }
...
free(a);
It is the basis of linked lists, trees and graphs, where nodes are created and deleted as needed. Advantages are no wastage of memory and flexible size; disadvantages are slower access and the risk of memory leaks and dangling pointers if free is forgotten or misused.
(b) Game tree
A game tree is a tree that represents all possible moves of a two-player game (such as tic-tac-toe or chess). Each node is a game position (state) and each edge is a legal move. The root is the current position; levels alternate between the two players (MAX and MIN). The leaves are terminal positions (win, lose, draw) which are given a score.
To choose the best move, the minimax algorithm is used: at MAX levels the child with the largest value is chosen and at MIN levels the child with the smallest value is chosen, and values are propagated up to the root. Alpha-beta pruning reduces the work by skipping branches that cannot affect the final decision. Since the tree grows exponentially (branching factor , depth gives about nodes), real programs limit the depth and use an evaluation function.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
What is stack? What are the different applications of stack? Explain stack operations with example.
Answer
Stack
A stack is a linear data structure in which insertion and deletion are done at only one end, called the top. It follows the LIFO (Last In First Out) rule: the element inserted last is removed first. Example: a pile of plates.
Applications of stack
- Function call management and recursion (call stack).
- Conversion of infix expressions to postfix or prefix.
- Evaluation of postfix and prefix expressions.
- Undo/redo in editors; back button in browsers.
- Checking balanced parentheses.
- Reversing a string or list.
- Depth-first search and backtracking (maze, N-queens).
Stack operations
push(x): insert element at the top. If the stack is full, it is overflow.pop(): remove and return the top element. If the stack is empty, it is underflow.peek()/top(): read the top element without removing it.isEmpty(),isFull(): test the state of the stack.
Array implementation (with top = -1 initially, size MAX):
void push(int x) {
if (top == MAX - 1) printf("Overflow");
else s[++top] = x;
}
int pop() {
if (top == -1) { printf("Underflow"); return -1; }
return s[top--];
}
Example. Start with an empty stack.
| Operation | Stack (bottom to top) | top |
|---|---|---|
| push(10) | 10 | 0 |
| push(20) | 10, 20 | 1 |
| push(30) | 10, 20, 30 | 2 |
| pop() returns 30 | 10, 20 | 1 |
| peek() returns 20 | 10, 20 | 1 |
| pop() returns 20 | 10 | 0 |
Each push and pop takes time.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
Differentiate between singly linked list and doubly linked list. How do you insert and delete a node from doubly linked list? Explain.
Answer
Singly vs doubly linked list
| Singly linked list | Doubly linked list |
|---|---|
Each node has data and one pointer (next). | Each node has data and two pointers (prev and next). |
| Traversal only in the forward direction. | Traversal in both directions. |
| Less memory per node. | More memory per node (extra pointer). |
| Deleting a given node needs the previous node, found by traversal (). | A given node can be deleted in using its prev pointer. |
| Simpler to implement. | Insertion and deletion need more pointer updates. |
Node structure of a doubly linked list:
struct node {
int data;
struct node *prev, *next;
};
struct node *head = NULL;
Insertion
At the beginning:
void insertBeg(int x) {
struct node *n = malloc(sizeof(struct node));
n->data = x; n->prev = NULL; n->next = head;
if (head != NULL) head->prev = n;
head = n;
}
After a given node p:
void insertAfter(struct node *p, int x) {
struct node *n = malloc(sizeof(struct node));
n->data = x;
n->next = p->next;
n->prev = p;
if (p->next != NULL) p->next->prev = n;
p->next = n;
}
At the end: traverse to the last node t, then set n->prev = t; n->next = NULL; t->next = n; (if the list is empty, head = n).
Deletion
Delete the first node:
void delBeg() {
if (head == NULL) return;
struct node *t = head;
head = head->next;
if (head != NULL) head->prev = NULL;
free(t);
}
Delete a given node p:
void delNode(struct node *p) {
if (p->prev != NULL) p->prev->next = p->next;
else head = p->next; /* p was first */
if (p->next != NULL) p->next->prev = p->prev;
free(p);
}
Insertion or deletion at a known position takes time; finding the position takes .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
What is shortest path? Explain Dijkstra algorithm for finding shortest path using suitable example.
Answer
Shortest path
In a weighted graph, the shortest path between two vertices is the path whose sum of edge weights is minimum among all paths between them. The single-source shortest path problem finds shortest paths from one source vertex to all other vertices.
Dijkstra's algorithm
It works for graphs with non-negative edge weights and uses a greedy strategy: repeatedly pick the unvisited vertex with the smallest known distance and relax its outgoing edges.
- Set
dist[source] = 0anddist[v] = infinityfor all other vertices; mark all vertices unvisited. - Select the unvisited vertex with the smallest
dist; mark it visited. - For each neighbour of : if , then set and
parent[v] = u. - Repeat steps 2 and 3 until all vertices are visited.
Dijkstra(G, s):
for each v: dist[v] = INF, visited[v] = false
dist[s] = 0
repeat n times:
u = unvisited vertex with minimum dist
visited[u] = true
for each neighbour v of u:
if dist[u] + w(u,v) < dist[v]:
dist[v] = dist[u] + w(u,v); parent[v] = u
Time complexity is with an array, and with a min-heap.
Example. Edges: A-B = 4, A-C = 2, B-C = 1, B-D = 5, C-D = 8, C-E = 10, D-E = 2 (undirected). Source = A.
| Step | Vertex chosen | A | B | C | D | E |
|---|---|---|---|---|---|---|
| Init | - | 0 | inf | inf | inf | inf |
| 1 | A (0) | 0 | 4 | 2 | inf | inf |
| 2 | C (2) | 0 | 3 (via C: 2+1) | 2 | 10 | 12 |
| 3 | B (3) | 0 | 3 | 2 | 8 (3+5) | 12 |
| 4 | D (8) | 0 | 3 | 2 | 8 | 10 (8+2) |
| 5 | E (10) | 0 | 3 | 2 | 8 | 10 |
Shortest distances from A: B = 3, C = 2, D = 8, E = 10. The paths are A-C-B (3), A-C (2), A-C-B-D (8) and A-C-B-D-E (10).
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
What is dynamic memory allocation? Compare data structure with abstract data type.
Answer
Dynamic memory allocation
Dynamic memory allocation means obtaining memory from the heap at run time as required and releasing it when it is no longer needed. In C it is done using malloc(), calloc(), realloc() and free().
int *p = (int *)malloc(5 * sizeof(int)); /* space for 5 integers */
p = (int *)realloc(p, 10 * sizeof(int)); /* grow to 10 */
free(p); /* release */
Compared with static allocation (fixed at compile time, e.g. int a[5];), it avoids wasting memory, allows structures such as linked lists and trees to grow and shrink, and gives the programmer control over lifetime. The price is slower allocation and the risk of memory leaks and dangling pointers.
Data structure vs abstract data type (ADT)
An ADT is a mathematical/logical model that specifies a set of data and the operations on it, without saying how they are implemented (for example Stack, Queue, List). A data structure is the concrete implementation of that model in a programming language, with actual storage and algorithms (for example a stack implemented using an array or a linked list).
| Abstract data type | Data structure |
|---|---|
| Logical view: what operations are done. | Implementation view: how they are done. |
| Independent of any programming language. | Written in a specific programming language. |
| Defines data values and operations only. | Defines storage organisation and code for operations. |
| Example: Stack ADT with push, pop. | Example: array-based or linked stack. |
| One ADT can have many implementations. | A data structure implements one or more ADTs. |
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
Explain algorithm for evaluation of postfix expression using stack
Answer
Evaluation of a postfix expression using a stack
In postfix (reverse Polish) notation the operator comes after its operands, e.g. a b +. No parentheses or precedence rules are needed, so the expression can be evaluated in one left-to-right scan with a stack of operands.
Algorithm
- Create an empty stack.
- Scan the expression from left to right, one symbol at a time.
- If the symbol is an operand, push its value onto the stack.
- If the symbol is an operator, pop two values: first pop gives (the right operand) and second pop gives (the left operand). Compute and push the result.
- After the whole expression is scanned, the single value left on the stack is the result.
evalPostfix(P):
for each symbol ch in P:
if ch is operand: push(value(ch))
else:
b = pop(); a = pop()
push(a ch b)
return pop()
The order matters for non-commutative operators (, , ): the second popped value is the left operand.
Example. Evaluate 5 6 2 + * 12 4 / -.
| Symbol | Action | Stack |
|---|---|---|
| 5 | push | 5 |
| 6 | push | 5, 6 |
| 2 | push | 5, 6, 2 |
| + | 6 + 2 = 8 | 5, 8 |
| * | 5 * 8 = 40 | 40 |
| 12 | push | 40, 12 |
| 4 | push | 40, 12, 4 |
| / | 12 / 4 = 3 | 40, 3 |
| - | 40 - 3 = 37 | 37 |
Result . Time complexity is for an expression of symbols.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
Explain queue as an ADT.
Answer
Queue as an ADT
A queue is a linear collection in which insertion takes place at one end (rear) and deletion at the other end (front). It follows FIFO (First In First Out). As an abstract data type, it is defined by its data and operations, independent of implementation.
ADT specification
Data: an ordered collection of elements with a front and a rear.
Operations:
create(): make an empty queue.enqueue(x): insert at the rear. Precondition: queue not full.dequeue(): remove and return the front element. Precondition: queue not empty.front(): return the front element without removing it.isEmpty(): true if the queue has no element.isFull(): true if no more elements can be added (bounded implementation).
Array implementation (linear queue)
#define MAX 100
int q[MAX], front = 0, rear = -1;
void enqueue(int x) {
if (rear == MAX - 1) printf("Overflow");
else q[++rear] = x;
}
int dequeue() {
if (front > rear) { printf("Underflow"); return -1; }
return q[front++];
}
Queue is empty when front > rear. A drawback is that freed positions at the front are not reused; a circular queue (using (rear+1) % MAX) removes this problem.
Linked implementation: enqueue adds a node at the tail and dequeue removes the head node; no fixed size limit.
Each operation takes time.
Types: simple queue, circular queue, double-ended queue (deque) and priority queue.
Applications: CPU/job scheduling, printer spooling, buffering in I/O, breadth-first search, call centre waiting lines.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
Write a recursive program to find GCD of two numbers.
Answer
Recursive GCD (Euclid's algorithm)
The GCD of two numbers and satisfies
The base case is , and each call reduces , so the recursion terminates.
#include <stdio.h>
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
int main() {
int x, y;
printf("Enter two numbers: ");
scanf("%d %d", &x, &y);
printf("GCD of %d and %d = %d\n", x, y, gcd(x, y));
return 0;
}
Trace for gcd(48, 18):
- gcd(48, 18) calls gcd(18, 12) since
- gcd(18, 12) calls gcd(12, 6) since
- gcd(12, 6) calls gcd(6, 0) since
- gcd(6, 0) returns 6
So . The time complexity is .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
What is linked list? How is it different from array?
Answer
Linked list
A linked list is a linear data structure made of nodes. Each node has a data field and a link (pointer) to the next node; the last node points to NULL. A pointer head holds the address of the first node. Nodes are created dynamically and are not stored in contiguous memory.
struct node {
int data;
struct node *next;
};
Types: singly linked list, doubly linked list and circular linked list.
Difference between linked list and array
| Array | Linked list |
|---|---|
| Elements stored in contiguous memory. | Nodes may be anywhere in memory, connected by pointers. |
| Size is fixed at declaration (static). | Size grows and shrinks at run time (dynamic). |
| Direct (random) access by index in . | Sequential access only; reaching the -th node takes . |
| Insertion/deletion in the middle needs shifting, . | Insertion/deletion needs only pointer changes, once the position is known. |
| No extra memory for links. | Extra memory for the pointer in each node. |
| Memory may be wasted (unused slots) or insufficient. | Memory is allocated as needed, no wastage. |
| Better cache performance. | Poorer cache performance. |
Arrays suit situations with frequent index access and fixed size; linked lists suit frequent insertions and deletions and unknown size.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
Hand test bubble sort with array of numbers 53, 42, 78, 3, 5, 2, 15 in ascending order.
Answer
Bubble sort
Bubble sort compares adjacent elements and swaps them if they are out of order. After each pass the largest remaining element moves ("bubbles") to its final position at the right end.
Array: 53, 42, 78, 3, 5, 2, 15 (ascending order).
Pass 1
- 53 > 42, swap: 42, 53, 78, 3, 5, 2, 15
- 53 < 78, no swap
- 78 > 3, swap: 42, 53, 3, 78, 5, 2, 15
- 78 > 5, swap: 42, 53, 3, 5, 78, 2, 15
- 78 > 2, swap: 42, 53, 3, 5, 2, 78, 15
- 78 > 15, swap: 42, 53, 3, 5, 2, 15, 78
Pass 2
- 42 < 53, no swap
- 53 > 3, swap: 42, 3, 53, 5, 2, 15, 78
- 53 > 5, swap: 42, 3, 5, 53, 2, 15, 78
- 53 > 2, swap: 42, 3, 5, 2, 53, 15, 78
- 53 > 15, swap: 42, 3, 5, 2, 15, 53, 78
Pass 3
- 42 > 3, swap: 3, 42, 5, 2, 15, 53, 78
- 42 > 5, swap: 3, 5, 42, 2, 15, 53, 78
- 42 > 2, swap: 3, 5, 2, 42, 15, 53, 78
- 42 > 15, swap: 3, 5, 2, 15, 42, 53, 78
Pass 4
- 3 < 5, no swap
- 5 > 2, swap: 3, 2, 5, 15, 42, 53, 78
- 5 < 15, 15 < 42: no swap
Result: 3, 2, 5, 15, 42, 53, 78
Pass 5
- 3 > 2, swap: 2, 3, 5, 15, 42, 53, 78
- remaining comparisons need no swap.
Pass 6: no swap occurs, so the array is sorted.
Sorted array: 2, 3, 5, 15, 42, 53, 78
Time complexity is in the worst and average case; with a "swapped" flag the best case is .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
What is hashing? Explain concept of hash table and hash function with example.
Answer
Hashing
Hashing is a technique to store and retrieve data directly using a key, by converting the key into an array index with a hash function. It gives average search, insertion and deletion time of .
Hash table
A hash table is an array of slots (buckets) in which each record is stored at the index computed from its key. The index of key is .
Hash function
A hash function maps a key to an index in . A good hash function is quick to compute, distributes keys uniformly and minimises collisions. Common methods:
- Division method: (choose prime).
- Mid-square method: square the key and take the middle digits.
- Folding method: split the key into parts and add them, then take mod .
Example. Table size , hash function . Insert keys 25, 42, 17, 38.
| Key | Index | |
|---|---|---|
| 25 | 5 | |
| 42 | 2 | |
| 17 | 7 | |
| 38 | 8 |
Table: index 2 holds 42, index 5 holds 25, index 7 holds 17, index 8 holds 38. To search 17, compute and check index 7 directly.
If a key such as 35 is inserted, is already occupied by 25. This is a collision, which is handled by collision resolution techniques such as chaining or open addressing.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
What is minimum spanning tree? Explain
Answer
Minimum spanning tree (MST)
A spanning tree of a connected, undirected graph with vertices is a subgraph that includes all vertices, is connected and has no cycle; it has exactly edges. For a weighted graph, the minimum spanning tree is the spanning tree whose total edge weight is the smallest. Applications: laying cable, road, pipeline and network design.
Two standard algorithms are Kruskal's and Prim's.
Kruskal's algorithm (greedy on edges)
- Sort all edges in non-decreasing order of weight.
- Take the next smallest edge; add it if it does not form a cycle with the edges already chosen (check using union-find), else discard it.
- Stop when edges are chosen.
Prim's algorithm (greedy on vertices)
- Start with any vertex in the tree.
- Repeatedly choose the minimum-weight edge connecting a tree vertex to a vertex outside the tree and add it.
- Stop when all vertices are in the tree.
Example. Edges: A-B = 4, A-C = 2, B-C = 1, B-D = 5, C-D = 8, C-E = 10, D-E = 2.
Kruskal: sorted edges B-C (1), A-C (2), D-E (2), A-B (4), B-D (5), C-D (8), C-E (10).
| Edge | Weight | Decision |
|---|---|---|
| B-C | 1 | accept |
| A-C | 2 | accept |
| D-E | 2 | accept |
| A-B | 4 | reject (A, B, C already connected, forms a cycle) |
| B-D | 5 | accept (joins {A,B,C} with {D,E}) |
Four edges () are chosen: B-C, A-C, D-E, B-D. Total weight .
Complexity: Kruskal ; Prim with an array, or with a heap.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2077 · 10 marks
Write short notes on:
- Tail recursion
- Collision resolution techniques
Answer
(a) Tail recursion
A recursive function is tail recursive if the recursive call is the very last action performed in the function: nothing remains to be done after the call returns (no multiplication, addition etc. on its result). Because the current stack frame is not needed after the call, a compiler can reuse it (tail-call optimisation), converting the recursion into a loop and using stack space.
Non-tail recursive factorial (multiplication happens after the call):
int fact(int n) {
if (n <= 1) return 1;
return n * fact(n - 1);
}
Tail recursive factorial (using an accumulator):
int fact(int n, int acc) {
if (n <= 1) return acc;
return fact(n - 1, n * acc); /* last action is the call */
}
The tail version is called as fact(5, 1). Tail recursion is easy to convert to iteration and avoids stack overflow for deep recursion.
(b) Collision resolution techniques
A collision occurs when two different keys hash to the same index. The two main families of resolution are:
1. Separate chaining (open hashing). Each table slot holds a linked list of all keys that hash to that slot. A colliding key is simply added to the list. Example with : keys 25 and 35 both go to slot 5, so slot 5 holds the list 25 -> 35. Table never overflows and deletion is easy, but extra memory is used for pointers and search can degrade to if lists grow long.
2. Open addressing (closed hashing). All keys are stored inside the table itself; on a collision another empty slot is searched by a probe sequence.
- Linear probing: try for . Simple, but causes primary clustering.
- Quadratic probing: try . Reduces primary clustering but causes secondary clustering.
- Double hashing: try using a second hash function. Gives the best distribution.
Example (linear probing, ): insert 25 at index 5; inserting 35 finds index 5 occupied, so it goes to index 6.
Another approach is rehashing, i.e. growing the table and re-inserting all keys when the load factor becomes high.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 10 marks
Define Queue. Write are different applications of queue? Explain queue operations with example.
Answer
Queue
A queue is a linear data structure in which elements are inserted at one end (rear) and deleted from the other end (front). It follows FIFO (First In First Out): the element inserted first is removed first, like people waiting in a line at a ticket counter.
Applications of queue
- CPU process scheduling and job scheduling.
- Printer spooling and other I/O buffering.
- Breadth-first traversal of graphs and trees.
- Handling requests in web servers and call centres.
- Simulation of real-life waiting lines (bank, traffic).
- Data transfer between asynchronous processes (keyboard buffer, pipes).
Queue operations
enqueue(x): add at the rear (overflow if full).dequeue(): remove and return the front element (underflow if empty).front(): look at the front element without removing it.isEmpty(),isFull().
#define MAX 5
int q[MAX], front = 0, rear = -1;
void enqueue(int x) {
if (rear == MAX - 1) printf("Overflow");
else q[++rear] = x;
}
int dequeue() {
if (front > rear) { printf("Underflow"); return -1; }
return q[front++];
}
Example. Start with an empty queue.
| Operation | Queue (front to rear) |
|---|---|
| enqueue(10) | 10 |
| enqueue(20) | 10, 20 |
| enqueue(30) | 10, 20, 30 |
| dequeue() returns 10 | 20, 30 |
| enqueue(40) | 20, 30, 40 |
| dequeue() returns 20 | 30, 40 |
Each operation takes time.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 10 marks
Explain circular linked list with example. How do you implement linked list operation in singly linked list? Explain.
Answer
Circular linked list
In a circular linked list the pointer of the last node points back to the first node instead of NULL, so the nodes form a ring. It can be singly or doubly linked. Any node can be a starting point, and the whole list can be traversed from any node. It is useful for round-robin scheduling and for implementing circular queues.
Example: with nodes 10, 20, 30, the links are 10 -> 20 -> 30 -> back to 10. An empty list has head == NULL; a one-node list has head->next == head.
Operations on a singly linked list
struct node { int data; struct node *next; };
struct node *head = NULL;
1. Traversal
void display() {
struct node *t = head;
while (t != NULL) { printf("%d ", t->data); t = t->next; }
}
2. Insertion
At the beginning:
void insertBeg(int x) {
struct node *n = malloc(sizeof(struct node));
n->data = x; n->next = head; head = n;
}
At the end:
void insertEnd(int x) {
struct node *n = malloc(sizeof(struct node)), *t = head;
n->data = x; n->next = NULL;
if (head == NULL) { head = n; return; }
while (t->next != NULL) t = t->next;
t->next = n;
}
After a given node p: n->next = p->next; p->next = n;
3. Deletion
First node:
void delBeg() {
if (head == NULL) return;
struct node *t = head; head = head->next; free(t);
}
A node with value :
void delValue(int x) {
struct node *t = head, *prev = NULL;
while (t != NULL && t->data != x) { prev = t; t = t->next; }
if (t == NULL) return; /* not found */
if (prev == NULL) head = t->next; /* first node */
else prev->next = t->next;
free(t);
}
4. Search
struct node *search(int x) {
for (struct node *t = head; t != NULL; t = t->next)
if (t->data == x) return t;
return NULL;
}
Insertion/deletion at the beginning take ; at the end, search and general deletion take .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 10 marks
What is binary search tree? Write a program to implement insertion and deletion algorithms in binary search tree.
Answer
Binary search tree (BST)
A binary search tree is a binary tree in which, for every node, all keys in the left subtree are smaller than the node's key and all keys in the right subtree are greater (duplicates are not allowed). An inorder traversal of a BST gives the keys in sorted order. Search, insertion and deletion take time, where is the height ( for a balanced tree, for a skewed one).
Program
#include <stdio.h>
#include <stdlib.h>
struct node {
int key;
struct node *left, *right;
};
struct node *newNode(int k) {
struct node *n = (struct node *)malloc(sizeof(struct node));
n->key = k; n->left = n->right = NULL;
return n;
}
/* insertion */
struct node *insert(struct node *root, int k) {
if (root == NULL) return newNode(k);
if (k < root->key) root->left = insert(root->left, k);
else if (k > root->key) root->right = insert(root->right, k);
return root;
}
struct node *minNode(struct node *t) {
while (t->left != NULL) t = t->left;
return t;
}
/* deletion */
struct node *delete(struct node *root, int k) {
if (root == NULL) return NULL;
if (k < root->key)
root->left = delete(root->left, k);
else if (k > root->key)
root->right = delete(root->right, k);
else {
if (root->left == NULL) { /* 0 or 1 child (right) */
struct node *t = root->right;
free(root);
return t;
}
if (root->right == NULL) { /* 1 child (left) */
struct node *t = root->left;
free(root);
return t;
}
struct node *s = minNode(root->right); /* inorder successor */
root->key = s->key;
root->right = delete(root->right, s->key);
}
return root;
}
void inorder(struct node *r) {
if (r) { inorder(r->left); printf("%d ", r->key); inorder(r->right); }
}
int main() {
struct node *root = NULL;
int a[] = {50, 30, 70, 20, 40, 60, 80};
for (int i = 0; i < 7; i++) root = insert(root, a[i]);
inorder(root); printf("\n"); /* 20 30 40 50 60 70 80 */
root = delete(root, 20); /* leaf */
root = delete(root, 30); /* one child */
root = delete(root, 50); /* two children */
inorder(root); printf("\n"); /* 40 60 70 80 */
return 0;
}
Explanation
Insertion: move left or right by comparing the key with the node until a NULL position is reached, and attach the new node there.
Deletion has three cases:
- Node is a leaf: remove it.
- Node has one child: replace the node by its child.
- Node has two children: copy the inorder successor (smallest key of the right subtree) into the node, then delete that successor from the right subtree.
In the sample run, deleting 20 (leaf), then 30 (one child, 40 takes its place), then 50 (two children, replaced by 60) leaves the inorder sequence 40 60 70 80.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 5 marks
How do you find complexity of algorithms? Explain
Answer
Complexity of algorithms
The complexity of an algorithm measures the resources it needs as a function of the input size . There are two kinds:
- Time complexity: the number of basic steps (comparisons, assignments, arithmetic operations) executed.
- Space complexity: the amount of memory needed (input plus auxiliary variables, stack).
How to find it
- Choose the input size and decide the basic operation to count.
- Count how many times each statement is executed, as a function of .
- Add the counts to get .
- Keep only the dominant (highest-order) term and drop constants; express using asymptotic notation.
Rules of thumb: a simple statement is ; a loop running times is ; nested loops multiply, e.g. two nested loops to give ; a loop where the variable is halved or doubled each time is ; consecutive blocks add, so the larger one dominates; for recursion, write a recurrence such as and solve it (here ).
Example.
for (i = 0; i < n; i++) /* n+1 tests */
for (j = 0; j < n; j++) /* n(n+1) tests */
sum = sum + a[i][j]; /* n*n times */
, so the time complexity is .
Asymptotic notations
- Big-O : upper bound (worst case).
- Big-Omega : lower bound (best case).
- Big-Theta : tight bound.
Algorithms are analysed for best, average and worst cases; for example linear search is best case and worst case.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 5 marks
Evaluate the expression ABCD-x+ using stack where A=5, B=4, C=3 and D=7
Answer
Postfix expression ABCD-x+ with A = 5, B = 4, C = 3, D = 7 becomes 5 4 3 7 - x +.
Scan left to right; push operands; for an operator pop the right operand first, then the left operand.
| Symbol | Action | Stack (bottom to top) |
|---|---|---|
| A (5) | push | 5 |
| B (4) | push | 5, 4 |
| C (3) | push | 5, 4, 3 |
| D (7) | push | 5, 4, 3, 7 |
| - | pop 7 and 3; compute ; push | 5, 4, -4 |
| x | pop -4 and 4; compute ; push | 5, -16 |
| + | pop -16 and 5; compute ; push | -11 |
The stack contains one value, so the result is -11.
This equals the infix expression .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 5 marks
What is priority queue? Why do you need this type of queue?
Answer
Priority queue
A priority queue is a queue in which every element has a priority, and the element with the highest priority (or lowest, depending on the convention) is served first, regardless of the order of arrival. Elements of equal priority are served in FIFO order.
Operations: insert(x, priority) adds an element, deleteMax()/deleteMin() removes the element with the highest/lowest priority, and peek() reads it. It can be implemented with an ordered or unordered array/list ( for insert or delete) or, most efficiently, with a binary heap ( for both).
Example: insert (task A, 2), (task B, 5), (task C, 1). With the largest number meaning highest priority, the removal order is B, A, C, whatever the insertion order.
Why it is needed
An ordinary queue serves strictly in arrival order, which is unsuitable when some items are more urgent. Priority queues are required in:
- CPU scheduling, where system processes get priority over user processes.
- Emergency handling, e.g. hospital patients by severity.
- Dijkstra's shortest path and Prim's MST algorithms (pick the minimum-distance vertex).
- Huffman coding (repeatedly take the two lowest-frequency nodes).
- Network packet scheduling and event-driven simulation.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 5 marks
Write a recursive program to find nth fibonacci number.
Answer
Recursive program for the nth Fibonacci number
The Fibonacci sequence is 0, 1, 1, 2, 3, 5, 8, ... defined by
#include <stdio.h>
int fib(int n) {
if (n == 0 || n == 1) /* base cases */
return n;
return fib(n - 1) + fib(n - 2);
}
int main() {
int n;
printf("Enter n: ");
scanf("%d", &n);
printf("Fibonacci(%d) = %d\n", n, fib(n));
return 0;
}
For : . The sequence is 0, 1, 1, 2, 3, 5, so the 5th term (counting from ) is 5.
This version recomputes the same values many times, so its time complexity is exponential, about , while stack depth is . It can be improved with memoisation or iteration to .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 5 marks
Explain array implementation of list.
Answer
Array implementation of a list
A list is an ordered collection of elements . In the array (static/sequential) implementation the elements are stored in consecutive memory locations of an array, and a variable n (or last) records the current number of elements. The -th element is at index and can be reached in time.
#define MAX 100
int list[MAX];
int n = 0; /* number of elements */
Insertion at position (0-based): check that the array is not full, shift elements from to the end one place to the right, place the new item, and increase n.
void insert(int pos, int x) {
if (n == MAX) { printf("List full"); return; }
for (int i = n - 1; i >= pos; i--)
list[i + 1] = list[i];
list[pos] = x;
n++;
}
Deletion at position : shift elements after one place to the left and decrease n.
void delete(int pos) {
if (pos < 0 || pos >= n) { printf("Invalid"); return; }
for (int i = pos; i < n - 1; i++)
list[i] = list[i + 1];
n--;
}
Traversal and search scan the array from index 0 to , taking .
Complexity: access ; insertion and deletion because of shifting (at the end, ).
Advantages: simple, fast random access, no pointer overhead. Disadvantages: fixed maximum size, wasted space if not full, and costly insertions and deletions.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 5 marks
Hand test selection sort with array of numbers 4, 71, 32, 19, 61, 2, -5 in descending order.
Answer
Selection sort (descending order)
In each pass, find the largest element in the unsorted part and swap it with the first element of that part.
Array: 4, 71, 32, 19, 61, 2, -5
| Pass | Unsorted part searched | Largest | Swap | Array after pass |
|---|---|---|---|---|
| 1 | 4, 71, 32, 19, 61, 2, -5 | 71 | with position 1 (value 4) | 71, 4, 32, 19, 61, 2, -5 |
| 2 | 4, 32, 19, 61, 2, -5 | 61 | with position 2 (value 4) | 71, 61, 32, 19, 4, 2, -5 |
| 3 | 32, 19, 4, 2, -5 | 32 | already in place | 71, 61, 32, 19, 4, 2, -5 |
| 4 | 19, 4, 2, -5 | 19 | already in place | 71, 61, 32, 19, 4, 2, -5 |
| 5 | 4, 2, -5 | 4 | already in place | 71, 61, 32, 19, 4, 2, -5 |
| 6 | 2, -5 | 2 | already in place | 71, 61, 32, 19, 4, 2, -5 |
The last element -5 is then automatically in place.
Sorted array in descending order: 71, 61, 32, 19, 4, 2, -5
Number of comparisons is ; time complexity in all cases.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 5 marks
Write a program to implement sequential search algorithm.
Answer
Sequential (linear) search
Sequential search examines the elements of a list one by one from the first, comparing each with the key, until a match is found or the list ends.
#include <stdio.h>
int seqSearch(int a[], int n, int key) {
for (int i = 0; i < n; i++)
if (a[i] == key)
return i; /* found at index i */
return -1; /* not found */
}
int main() {
int a[100], n, key, i, pos;
printf("Enter number of elements: ");
scanf("%d", &n);
printf("Enter %d elements: ", n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
printf("Enter element to search: ");
scanf("%d", &key);
pos = seqSearch(a, n, key);
if (pos == -1)
printf("%d not found\n", key);
else
printf("%d found at position %d\n", key, pos + 1);
return 0;
}
Complexity: best case (key is first), worst and average case . It does not need the list to be sorted, and works for arrays and linked lists.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 5 marks
What is graph traversal? Explain.
Answer
Graph traversal
Graph traversal means visiting every vertex of a graph exactly once in a systematic way, starting from a given source vertex. A visited array is used so that a vertex is not processed twice (graphs may contain cycles). The two standard methods are breadth-first search and depth-first search.
1. Breadth-First Search (BFS)
Visits all vertices at distance 1 from the source, then distance 2, and so on, using a queue.
- Mark the source visited and enqueue it.
- Dequeue a vertex , process it, and enqueue all its unvisited neighbours (marking them visited).
- Repeat until the queue is empty.
2. Depth-First Search (DFS)
Goes as deep as possible along a path before backtracking, using a stack (or recursion).
- Mark the source visited and push it.
- Visit an unvisited neighbour of the top vertex and push it; if there is none, pop (backtrack).
- Repeat until the stack is empty.
Example. Edges: A-B, A-C, B-D, C-D, D-E. Start at A (neighbours taken alphabetically).
- BFS: A, B, C, D, E
- DFS: A, B, D, C, E (A to B to D, then D's unvisited neighbour C, then back to D to E)
Both take time with an adjacency list. Uses: finding connected components, shortest path in unweighted graphs (BFS), cycle detection, topological sorting (DFS), and solving mazes.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2078 · 5 marks
Write short notes on:
- Divide and Conquer sorting
- AVL Tree
Answer
(a) Divide and conquer sorting
Divide and conquer solves a problem in three steps: divide it into smaller subproblems, conquer them by solving recursively (a very small problem is solved directly), and combine the sub-solutions into the final answer. Sorting algorithms based on it are merge sort and quick sort.
Merge sort: divide the array into two halves, sort each half recursively, then merge the two sorted halves into one sorted array. Work is in the combine step. Recurrence gives in all cases, with extra space; it is stable.
Quick sort: choose a pivot, partition the array so that smaller elements are on its left and larger elements on its right, then sort both parts recursively. Work is in the divide step; no combine step is needed. Average time , worst case (bad pivots), in-place.
(b) AVL tree
An AVL tree (Adelson-Velsky and Landis) is a self-balancing binary search tree in which, for every node, the heights of the left and right subtrees differ by at most 1. The balance factor of a node is
After an insertion or deletion, if some node gets , the tree is rebalanced by rotations:
- LL case (inserted in left subtree of left child): single right rotation.
- RR case (right of right child): single left rotation.
- LR case (right of left child): left rotation on the child, then right rotation.
- RL case (left of right child): right rotation on the child, then left rotation.
Example: inserting 10, 20, 30 in order gives a right-skewed tree with (RR case); a left rotation at 10 makes 20 the root with children 10 and 30.
An AVL tree with nodes has height , so search, insertion and deletion all take time, unlike an ordinary BST which can degrade to .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 10 marks
Why do we need to balance the binary search tree? Justify with an example. Create an AVL tree from the data 24, 12, 8, 15, 35, 30, 57, 40, 45, 78.
Answer
Why balancing is needed. A binary search tree (BST) gives search, insert and delete in , where is the height. The shape of the tree depends on the order of insertion. If keys arrive in sorted order the BST degenerates into a linked list with , so every operation costs . A balanced tree keeps , so all operations stay .
Example. Insert 10, 20, 30, 40, 50 into an ordinary BST. Each key becomes the right child of the previous one, giving a chain of height 5. Searching 50 needs 5 comparisons, and for keys it would need . If the tree is kept balanced (an AVL tree), the same 5 keys form a tree of height 3 (root 20, children 10 and 40, and 30, 50 under 40), and for at most about 20 comparisons are needed.
An AVL tree is a BST in which, for every node, the balance factor . After an insertion that makes some node's BF become , the tree is repaired by rotations (LL, RR, LR, RL).
Construction of the AVL tree for 24, 12, 8, 15, 35, 30, 57, 40, 45, 78.
- Insert 24: root 24.
- Insert 12: left child of 24.
- Insert 8: left of 12. Node 24 has BF (LL case). Right rotation at 24 gives root 12 with children 8 and 24.
- Insert 15: goes to the left of 24. Tree: 12 (8, 24(15, -)). Balanced.
- Insert 35: right of 24. Tree: 12 (8, 24(15, 35)). Balanced.
- Insert 30: left of 35. Node 12 now has BF (RR case, since 24 is right-heavy). Left rotation at 12 gives root 24 with left subtree 12(8, 15) and right subtree 35(30, -).
- Insert 57: right of 35. Balanced: 35(30, 57).
- Insert 40: left of 57. Tree: 24 ( 12(8,15), 35(30, 57(40,-)) ). Balanced.
- Insert 45: right of 40. Node 57 has BF and its left child 40 is right-heavy (LR case). Left rotation at 40 then right rotation at 57 makes 45 the subtree root with children 40 and 57. Now 35(30, 45(40, 57)).
- Insert 78: right of 57. Node 35 has BF and its right child 45 is right-heavy (RR case). Left rotation at 35 makes 45 the subtree root with left child 35(30, 40) and right child 57(-, 78).
Final AVL tree
24
/ \
12 45
/ \ / \
8 15 35 57
/ \ \
30 40 78
Check: 24's left subtree has height 2 and right subtree has height 3 (BF ); 45 has two subtrees of height 2 (BF ); every other node has . In-order traversal gives 8, 12, 15, 24, 30, 35, 40, 45, 57, 78, which is sorted, so the BST property holds.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 10 marks
How recursive algorithm uses stack to store intermediate results? Illustrate with an example. Convert the infix expression A+B-(CD/E+F)-GH into postfix expression using stack.
Answer
Recursion and the stack. When a function calls itself, each call needs its own parameters, local variables and return address. The system keeps these in an activation record (stack frame) pushed onto the call stack. The most recent call must finish first, which is exactly LIFO order. When the base case is reached the frames are popped one by one, and each returned value is used to complete the pending computation of the caller. So the stack stores the intermediate (pending) results.
Example: factorial.
int fact(int n) {
if (n <= 1) return 1; /* base case */
return n * fact(n - 1); /* recursive case */
}
For fact(4):
- Calling phase (push):
fact(4)waits forfact(3), which waits forfact(2), which waits forfact(1). The stack holds frames n=4, 3, 2, 1 (top is n=1). fact(1)returns 1 and its frame is popped.- Returning phase (pop):
fact(2)computes ,fact(3)computes ,fact(4)computes .
Infix to postfix: A + B - (C * D / E + F) - G * H
Rules: operands go to output; an operator pops operators of higher or equal precedence (left associative) before being pushed; ( is pushed; ) pops until (.
| Symbol | Stack (bottom to top) | Output |
|---|---|---|
| A | A | |
| + | + | A |
| B | + | A B |
| - | - (pop +) | A B + |
| ( | - ( | A B + |
| C | - ( | A B + C |
| * | - ( * | A B + C |
| D | - ( * | A B + C D |
| / | - ( / (pop *) | A B + C D * |
| E | - ( / | A B + C D * E |
| + | - ( + (pop /) | A B + C D * E / |
| F | - ( + | A B + C D * E / F |
| ) | - (pop +, remove "(") | A B + C D * E / F + |
| - | - (pop -, push -) | A B + C D * E / F + - |
| G | - | A B + C D * E / F + - G |
| * | - * | A B + C D * E / F + - G |
| H | - * | A B + C D * E / F + - G H |
| end | pop all | A B + C D * E / F + - G H * - |
Postfix expression:
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 10 marks
How do you insert and delete a node at k^th position of the doubly linked list? Describe the process of implementing stack and queue using linked list.
Answer
Doubly linked list node.
struct node {
int data;
struct node *prev, *next;
};
Insertion at the k-th position (positions start at 1; head is the first node).
- Create a new node
nand store the data. - If :
n->next = head; n->prev = NULL;ifhead != NULLsethead->prev = n; thenhead = n. - Otherwise move a pointer
pto the -th node. If the list is shorter, report an invalid position. - Set
n->next = p->next; n->prev = p; - If
p->next != NULL, setp->next->prev = n. - Set
p->next = n.
struct node *insertK(struct node *head, int x, int k) {
struct node *n = malloc(sizeof(struct node)), *p = head;
n->data = x;
if (k == 1) {
n->prev = NULL; n->next = head;
if (head) head->prev = n;
return n;
}
for (int i = 1; i < k - 1 && p; i++) p = p->next;
if (!p) { free(n); printf("Invalid position\n"); return head; }
n->next = p->next; n->prev = p;
if (p->next) p->next->prev = n;
p->next = n;
return head;
}
Deletion of the k-th node.
- If the list is empty, report underflow.
- Move a pointer
pto the -th node; if it does not exist, report an invalid position. - If
p->prev != NULL, setp->prev->next = p->next; otherwise (deleting the first node) sethead = p->next. - If
p->next != NULL, setp->next->prev = p->prev. free(p).
struct node *deleteK(struct node *head, int k) {
struct node *p = head;
for (int i = 1; i < k && p; i++) p = p->next;
if (!p) { printf("Invalid position\n"); return head; }
if (p->prev) p->prev->next = p->next; else head = p->next;
if (p->next) p->next->prev = p->prev;
free(p);
return head;
}
Both operations take time for the traversal, and the pointer changes themselves take .
Stack using a linked list. A stack is LIFO, so the head of a singly linked list is used as the top. Both operations then work at the head and take .
- Push: create a node, set
new->next = top, thentop = new. - Pop: if
top == NULLreport underflow; else savet = top, settop = top->next, returnt->data, andfree(t). - Stack empty when
top == NULL. There is no overflow except heap exhaustion, and the size is dynamic.
Queue using a linked list. A queue is FIFO, so two pointers are kept: front (delete end) and rear (insert end).
- Enqueue: create a node with
next = NULL. If the queue is empty, setfront = rear = new; otherwiserear->next = new; rear = new. - Dequeue: if
front == NULLreport underflow; elset = front; front = front->next;iffrontbecomesNULLalso setrear = NULL; return the data andfree(t). - Both operations take time and the queue never becomes "full" while memory is available.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 5 marks
Sort the numbers 82,73,12,39,26,88,2,9,60,41 using shell sort.
Answer
Shell sort sorts elements that are a gap apart using insertion sort, and reduces the gap until it is 1. For use gaps 5, 2, 1.
Initial array: 82, 73, 12, 39, 26, 88, 2, 9, 60, 41
Gap = 5. Compare the pairs (index 0, 5), (1, 6), (2, 7), (3, 8), (4, 9):
- (82, 88): in order.
- (73, 2): swap.
- (12, 9): swap.
- (39, 60): in order.
- (26, 41): in order.
Result: 82, 2, 9, 39, 26, 88, 73, 12, 60, 41
Gap = 2. Sort the two interleaved sub-lists by insertion sort.
- Even positions: 82, 9, 26, 73, 60 sorted gives 9, 26, 60, 73, 82.
- Odd positions: 2, 39, 88, 12, 41 sorted gives 2, 12, 39, 41, 88.
Result: 9, 2, 26, 12, 60, 39, 73, 41, 82, 88
Gap = 1. Ordinary insertion sort on the nearly sorted array: 2 moves before 9; 12 moves before 26; 39 moves before 60; 41 moves before 60; the rest are already in place.
Sorted array: 2, 9, 12, 26, 39, 41, 60, 73, 82, 88
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 5 marks
Why do we need asymptotic notation? Describe about Big oh notation with its curve.
Answer
Need for asymptotic notation. The exact running time of an algorithm depends on the machine, compiler, language and input, so it is hard to compare algorithms by measured time. Asymptotic notation describes how the running time (or space) grows as the input size , ignoring constants and lower-order terms. It lets us compare algorithms independently of hardware, and predict how they behave for large inputs. For example, is simply described as .
Big O notation (upper bound). if there exist positive constants and such that
So is an asymptotic upper bound on ; it is used to state the worst-case growth of an algorithm.
Curve. For , may lie above or below . From onward, the curve of stays above the curve of :
time
| c*g(n)
| /
| / ..... f(n)
| / ....
| /..
| /.
| /.
| /.
|_______/_._________________________ n
n0
Example. . Choose , then for all , so with and .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 5 marks
Define queue. Explain about enqueue and dequeue operation in circular queue.
Answer
Queue. A queue is a linear data structure in which insertion takes place at one end (rear) and deletion takes place at the other end (front), following the FIFO (First In First Out) principle. The main operations are enqueue (insert), dequeue (delete), and checking empty/full.
Circular queue. In a linear array queue, once rear reaches the last index no new element can be inserted even if free space exists at the front after dequeues. In a circular queue the array is treated as a ring: the position after the last index is index 0, so freed space is reused. Indices move using modulo arithmetic: .
Initially front = rear = -1.
Enqueue(x):
- If
(rear + 1) % N == front, the queue is full: report overflow. - If the queue is empty (
front == -1), setfront = 0. - Set
rear = (rear + 1) % N. - Set
Q[rear] = x.
Dequeue():
- If
front == -1, the queue is empty: report underflow. - Set
x = Q[front]. - If
front == rear, the queue had one element, so setfront = rear = -1. - Otherwise
front = (front + 1) % N. - Return
x.
void enqueue(int x) {
if ((rear + 1) % N == front) { printf("Overflow\n"); return; }
if (front == -1) front = 0;
rear = (rear + 1) % N;
Q[rear] = x;
}
int dequeue() {
if (front == -1) { printf("Underflow\n"); return -1; }
int x = Q[front];
if (front == rear) front = rear = -1;
else front = (front + 1) % N;
return x;
}
Both operations take time. With this convention all cells can be used.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 5 marks
Write a program to implement binary search.
Answer
Binary search works on a sorted array. It compares the key with the middle element and discards half of the array each time, so it runs in .
#include <stdio.h>
int binarySearch(int a[], int n, int key) {
int low = 0, high = n - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (a[mid] == key)
return mid; /* found */
else if (key < a[mid])
high = mid - 1; /* search left half */
else
low = mid + 1; /* search right half */
}
return -1; /* not found */
}
int main() {
int a[100], n, key, i, pos;
printf("Enter number of elements: ");
scanf("%d", &n);
printf("Enter %d elements in ascending order:\n", n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
printf("Enter element to search: ");
scanf("%d", &key);
pos = binarySearch(a, n, key);
if (pos == -1)
printf("Element not found\n");
else
printf("Element found at position %d\n", pos + 1);
return 0;
}
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 5 marks
Assume you have to store the data {0,1,2,4,5,7} into a hash table of size 5, with hash function, h(x)=x%5. Apply linear probing and double hashing as collision resolution techniques.
Answer
Table size (slots 0 to 4), . Keys: 0, 1, 2, 4, 5, 7.
Note that there are 6 keys but only 5 slots, so one key cannot be stored unless the table is enlarged.
Initial hash values: .
(a) Linear probing: .
- 0 goes to slot 0; 1 to slot 1; 2 to slot 2; 4 to slot 4.
- 5: is occupied, try 1 (occupied), 2 (occupied), 3 (free), so 5 goes to slot 3.
- 7: is occupied, then 3, 4, 0, 1 are all occupied. The table is full, so 7 cannot be inserted (overflow; the table must be resized, for example to size 7 or 11 and rehashed).
| Slot | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| Key | 0 | 1 | 2 | 5 | 4 |
(b) Double hashing: , with and the second hash (a value from 1 to 3).
- 0, 1, 2, 4 go to slots 0, 1, 2, 4 without collision.
- 5: , . Probes: slot 0 (occupied), slot 1 (occupied), slot 2 (occupied), slot 3 (free). So 5 goes to slot 3.
- 7: , . Probes: slot 2, slot 4, slot 1, slot 3, slot 0, all occupied. The table is full, so 7 cannot be placed (overflow).
| Slot | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| Key | 0 | 1 | 2 | 5 | 4 |
Both methods place 0, 1, 2, 5, 4 in the same slots here, and both fail for 7 because five keys already fill the table. Double hashing generally spreads keys better, since the probe step depends on the key and so avoids primary clustering.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 5 marks
In which case the position of pivot element in quick sort always either in the last or the first position? Create a max heap from the numbers. {10,12,53,34,23,77,59,66,5,8}
Answer
Pivot at the first or last position. In quick sort the pivot ends up at its final sorted position after partitioning. That position is always at an extreme (first or last) when the pivot is the smallest or the largest element of the sub-array every time. This happens when the pivot is chosen as the first or last element and the array is already sorted in ascending or descending order (or all keys are equal). Each partition then splits the array into sizes and , giving the worst case .
Building a max heap from {10, 12, 53, 34, 23, 77, 59, 66, 5, 8}. Insert the numbers one by one in the given order into the array representation (children of index are and ), moving each new element up while it is larger than its parent.
| Insert | Heap after insertion |
|---|---|
| 10 | 10 |
| 12 | 12, 10 (swap with 10) |
| 53 | 53, 10, 12 (swap with 12) |
| 34 | 53, 34, 12, 10 (34 swaps with 10) |
| 23 | 53, 34, 12, 10, 23 (no swap) |
| 77 | 77, 34, 53, 10, 23, 12 (77 swaps with 12, then with 53) |
| 59 | 77, 34, 59, 10, 23, 12, 53 (59 swaps with 53) |
| 66 | 77, 66, 59, 34, 23, 12, 53, 10 (66 swaps with 10, then with 34) |
| 5 | 77, 66, 59, 34, 23, 12, 53, 10, 5 (no swap) |
| 8 | 77, 66, 59, 34, 23, 12, 53, 10, 5, 8 (no swap) |
Final max heap (array): 77, 66, 59, 34, 23, 12, 53, 10, 5, 8
77
/ \
66 59
/ \ / \
34 23 12 53
/ \ /
10 5 8
Every parent is greater than or equal to its children.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 5 marks
Evaluate the postfix expression 574-*8/4+ using stack.
Answer
Postfix expression: 5 7 4 - * 8 / 4 +. Scan left to right; push operands; on an operator pop the top two values (first pop is the right operand , second pop is the left operand ), compute and push the result.
| Symbol | Action | Stack (bottom to top) |
|---|---|---|
| 5 | push | 5 |
| 7 | push | 5, 7 |
| 4 | push | 5, 7, 4 |
| - | 5, 3 | |
| * | 15 | |
| 8 | push | 15, 8 |
| / | 1.875 | |
| 4 | push | 1.875, 4 |
| + | 5.875 |
Result = 5.875 (equivalent to the infix expression ). With integer division the result would be 5.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2079 · 5 marks
Write short noes on:
a. Priority Queue
b. Breadth First traversal of a graph
Answer
(a) Priority queue. A priority queue is an abstract data type in which every element has a priority, and the element with the highest priority (or lowest, in a min-priority queue) is removed first, regardless of its arrival order. Elements with equal priority are served in FIFO order.
- Operations:
insert(x, priority),deleteMax/deleteMin(),peek(),isEmpty(). - Implementations: unsorted array/list (insert , delete ), sorted list (insert , delete ), and the binary heap (both ), which is the most common.
- Applications: CPU process scheduling, Dijkstra's and Prim's algorithms, Huffman coding, event-driven simulation, and operating system job queues.
(b) Breadth First Traversal (BFS) of a graph. BFS visits the start vertex, then all its neighbours, then the neighbours of those neighbours, level by level. It uses a queue and a visited array.
Algorithm:
- Mark the start vertex visited and enqueue it.
- While the queue is not empty: dequeue a vertex and print it; for each unvisited neighbour of , mark it visited and enqueue it.
Example: for the graph with edges A-B, A-C, B-D, C-D, D-E starting at A, the order is A, B, C, D, E.
Time complexity is with an adjacency list. BFS finds the shortest path (fewest edges) in an unweighted graph and is used for connected components and level-order traversal.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 10 marks
Explain queue as an ADT. Write a program to implement linear queue. Compare linear queue with circular queue.
Answer
Queue as an ADT. A queue is a linear collection of items in which insertion is done at the rear and deletion at the front (FIFO). As an abstract data type it is defined by its data and operations, independent of implementation.
- Data: an ordered collection of elements with a
frontand arear. - Operations:
create()makes an empty queue.enqueue(x)adds at the rear (error if full).dequeue()removes and returns the front element (error if empty).peek()returns the front element without removing it.isEmpty()andisFull()test the state.
- Axiom:
dequeue(enqueue(create(), x))returns , and elements leave in the order in which they entered.
Program: linear queue using an array (C).
#include <stdio.h>
#define MAX 5
int q[MAX], front = -1, rear = -1;
void enqueue(int x) {
if (rear == MAX - 1) { printf("Queue overflow\n"); return; }
if (front == -1) front = 0;
q[++rear] = x;
}
void dequeue() {
if (front == -1 || front > rear) { printf("Queue underflow\n"); return; }
printf("Deleted: %d\n", q[front++]);
}
void display() {
if (front == -1 || front > rear) { printf("Queue empty\n"); return; }
for (int i = front; i <= rear; i++) printf("%d ", q[i]);
printf("\n");
}
int main() {
int ch, x;
do {
printf("1.Enqueue 2.Dequeue 3.Display 4.Exit: ");
scanf("%d", &ch);
switch (ch) {
case 1: printf("Value: "); scanf("%d", &x); enqueue(x); break;
case 2: dequeue(); break;
case 3: display(); break;
}
} while (ch != 4);
return 0;
}
Linear queue vs circular queue.
| Linear queue | Circular queue |
|---|---|
Rear moves only forward; after rear = MAX-1 no insertion is possible | Rear wraps to index 0 using (rear+1) % MAX |
| Space freed by dequeue is never reused (false overflow) | Freed space is reused, so memory is used efficiently |
Full test: rear == MAX-1 | Full test: (rear+1) % MAX == front |
Empty test: front > rear or front == -1 | Empty test: front == -1 |
| Simple to implement | Slightly more complex because of modulo arithmetic |
| Poor use of memory | Better use of memory |
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 10 marks
Define hash table and hash function. What is collision in hashing? Explain linear probing and quadratic probing with suitable example.
Answer
Hash table. A hash table is a data structure that stores key-value records in an array and uses a hash function to compute the array index directly from the key, giving average search, insert and delete.
Hash function. A function that maps a key to an index in , where is the table size. A good hash function is fast to compute and distributes keys uniformly. Example (division method): .
Collision. A collision occurs when two different keys hash to the same index, , . It must be resolved by a collision-resolution technique, such as chaining or open addressing (linear probing, quadratic probing, double hashing).
Both of the following are open addressing methods: all keys are stored in the table itself, and on collision other slots are probed in a fixed sequence.
Linear probing. Probe sequence: for (check the next slot sequentially). It can cause primary clustering (long runs of filled slots).
Example: , , insert 89, 18, 49, 58, 69.
- 89 goes to slot 9; 18 goes to slot 8.
- 49: slot 9 is occupied, next slot 0 is free, so 49 goes to slot 0.
- 58: slots 8, 9, 0 occupied, so 58 goes to slot 1.
- 69: slots 9, 0, 1 occupied, so 69 goes to slot 2.
| Slot | 0 | 1 | 2 | 3-7 | 8 | 9 |
|---|---|---|---|---|---|---|
| Key | 49 | 58 | 69 | empty | 18 | 89 |
Quadratic probing. Probe sequence: for (offsets 0, 1, 4, 9, ...). It avoids primary clustering but can cause milder secondary clustering (keys with the same hash follow the same probe path).
Same keys, :
- 89 goes to slot 9; 18 goes to slot 8.
- 49: slot 9 occupied; is free, so 49 goes to slot 0.
- 58: slot 8 occupied; occupied; is free, so 58 goes to slot 2.
- 69: slot 9 occupied; occupied; is free, so 69 goes to slot 3.
| Slot | 0 | 1 | 2 | 3 | 4-7 | 8 | 9 |
|---|---|---|---|---|---|---|---|
| Key | 49 | empty | 58 | 69 | empty | 18 | 89 |
Quadratic probing may fail to find an empty slot if the table is more than half full (unless is prime and the load factor is below 0.5).
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 10 marks
Explain AVL tree with example. Also, explain balancing algorithm for this tree.
Answer
AVL tree. An AVL tree (Adelson-Velsky and Landis) is a self-balancing binary search tree in which, for every node, the heights of the left and right subtrees differ by at most 1. The balance factor is
Because the height is always , search, insertion and deletion take time.
Example. The tree with root 20, left child 10 (children 5 and 15) and right child 30 is an AVL tree: every node has . If we then insert 3 (as the left child of 5), node 20 gets , so the tree is no longer an AVL tree and must be rebalanced (an LL case, fixed by a right rotation at 20, giving root 10 with children 5(3, -) and 20(15, 30)).
Balancing algorithm. After inserting a key as in an ordinary BST, walk back up from the new node to the root, updating heights and balance factors. At the first (lowest) node with , let be the child of on the taller side and apply one of four rotations:
- LL case ( and ; inserted into the left subtree of the left child): a single right rotation at . The left child becomes the root of the subtree, becomes its right child, and 's old right subtree becomes 's left subtree.
- RR case ( and ): a single left rotation at . The right child becomes the root, becomes its left child, and 's old left subtree becomes 's right subtree.
- LR case ( and ): left rotation at , then right rotation at . The grandchild (right child of ) becomes the subtree root.
- RL case ( and ): right rotation at , then left rotation at .
Pseudo-code:
insert(node, key):
ordinary BST insertion
update height(node)
bf = height(node.left) - height(node.right)
if bf > 1 and key < node.left.key: return rotateRight(node) // LL
if bf < -1 and key > node.right.key: return rotateLeft(node) // RR
if bf > 1 and key > node.left.key: node.left = rotateLeft(node.left); return rotateRight(node) // LR
if bf < -1 and key < node.right.key: node.right = rotateRight(node.right); return rotateLeft(node) // RL
return node
Illustration (RR). Inserting 10, 20, 30 gives the chain 10 -> 20 -> 30, with . A left rotation at 10 makes 20 the root with children 10 and 30, restoring balance. Each rotation takes , and at most one rotation (single or double) is needed per insertion, so insertion remains . For deletion, rebalancing may be needed at several ancestors, up to the root.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 5 marks
What is asymptotic analysis? Explain theta notation with example.
Answer
Asymptotic analysis. Asymptotic analysis studies how the running time or memory use of an algorithm grows as the input size becomes very large. It ignores machine-dependent constants and lower-order terms, so that algorithms can be compared by their order of growth. The common notations are Big O (upper bound), Omega (lower bound) and Theta (tight bound).
Theta notation (). if there exist positive constants , and such that
So bounds from both above and below: it is a tight bound, and exactly when and . For large , the curve of is sandwiched between and .
Example. Show .
- Lower bound: for all , so .
- Upper bound: for , and , so , giving .
Hence for all , with , so .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 5 marks
Explain push and pop operations of stack. What are different applications of stack?
Answer
A stack is a linear data structure in which insertion and deletion are done only at one end, called the top (LIFO: Last In First Out).
Push (insert). Using an array S[MAX] with top = -1 initially:
- If
top == MAX - 1, report stack overflow and stop. - Increment
top. - Set
S[top] = x.
Pop (delete).
- If
top == -1, report stack underflow and stop. - Set
x = S[top]. - Decrement
top. - Return
x.
void push(int x) {
if (top == MAX - 1) printf("Overflow\n");
else S[++top] = x;
}
int pop() {
if (top == -1) { printf("Underflow\n"); return -1; }
return S[top--];
}
Both operations take time.
Applications of a stack:
- Function calls and recursion (the call stack stores return addresses and local variables).
- Conversion of expressions: infix to postfix or prefix.
- Evaluation of postfix and prefix expressions.
- Balanced parentheses checking and syntax parsing in compilers.
- Undo/redo in editors, and back/forward navigation in browsers.
- Reversing a string or list.
- Depth-first search of graphs, and backtracking (maze solving, N-queens).
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 5 marks
Explain tail recursion with example. Compare recursion with iteration.
Answer
Tail recursion. A recursive function is tail recursive if the recursive call is the very last operation executed in the function, so nothing remains to be done after the call returns. The result of the recursive call is returned directly. Because no pending work remains, a compiler can reuse the same stack frame (tail-call optimisation) and convert the recursion into a loop, using stack space.
Example. Factorial in the ordinary (non-tail) form is return n * fact(n-1); where a multiplication still waits after the call. The tail-recursive version uses an accumulator:
int factTail(int n, int acc) {
if (n <= 1) return acc;
return factTail(n - 1, n * acc); /* last action is the call */
}
/* call: factTail(4, 1) -> factTail(3,4) -> factTail(2,12) -> factTail(1,24) -> 24 */
Recursion vs iteration.
| Recursion | Iteration |
|---|---|
| A function calls itself until a base case is reached | A loop (for/while) repeats a block until a condition fails |
| Uses the call stack, so extra memory, usually | Constant extra memory, usually |
| Slower because of function-call overhead | Generally faster |
| Risk of stack overflow for deep recursion or a missing base case | No such risk; a wrong condition causes an infinite loop |
| Code is shorter and more natural for tree, graph and divide-and-conquer problems (Tower of Hanoi, tree traversal) | Code can be longer for such problems |
| Termination by base case | Termination by loop condition |
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 5 marks
Trace selection sort algorithm with array of numbers 2, 81, 6, 45, 11, 21, 23, 41, and 11.
Answer
Selection sort: in pass , find the minimum of the unsorted part (positions to the end) and swap it with the element at position . The array has elements, so 8 passes are needed.
Initial: 2, 81, 6, 45, 11, 21, 23, 41, 11
| Pass | Minimum found | Array after the pass (sorted part before the bar) |
|---|---|---|
| 1 | 2 (already in position 1) | 2 | 81, 6, 45, 11, 21, 23, 41, 11 |
| 2 | 6, swap with 81 | 2, 6 | 81, 45, 11, 21, 23, 41, 11 |
| 3 | 11 (first one), swap with 81 | 2, 6, 11 | 45, 81, 21, 23, 41, 11 |
| 4 | 11 (last one), swap with 45 | 2, 6, 11, 11 | 81, 21, 23, 41, 45 |
| 5 | 21, swap with 81 | 2, 6, 11, 11, 21 | 81, 23, 41, 45 |
| 6 | 23, swap with 81 | 2, 6, 11, 11, 21, 23 | 81, 41, 45 |
| 7 | 41, swap with 81 | 2, 6, 11, 11, 21, 23, 41 | 81, 45 |
| 8 | 45, swap with 81 | 2, 6, 11, 11, 21, 23, 41, 45 | 81 |
Sorted array: 2, 6, 11, 11, 21, 23, 41, 45, 81
The number of comparisons is and the time complexity is in all cases.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 5 marks
Explain binary search with an example. What is the time complexity of binary search?
Answer
Binary search. Binary search finds a key in a sorted array. It compares the key with the middle element; if equal the search ends, if the key is smaller the search continues in the left half, otherwise in the right half. Each step halves the search range.
Algorithm: low = 0, high = n-1; while low <= high: mid = (low + high) / 2; if a[mid] == key return mid; else if key < a[mid] set high = mid - 1; else low = mid + 1. If the loop ends, the key is absent.
Example. Array: 5, 12, 18, 23, 34, 45, 56 (indices 0 to 6). Search for 45.
| Step | low | high | mid | a[mid] | Decision |
|---|---|---|---|---|---|
| 1 | 0 | 6 | 3 | 23 | 45 > 23, so low = 4 |
| 2 | 4 | 6 | 5 | 45 | found at index 5 |
Found in 2 comparisons, while linear search would need 6.
Time complexity. Each iteration halves the range: . The number of iterations satisfies , so .
- Worst and average case: .
- Best case (key at the middle): .
- Space: for the iterative version.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 5 marks
Write Dijkstra’s algorithm to find shortest path between any two vertices of a graph.
Answer
Dijkstra's algorithm finds the shortest path from a source vertex to all other vertices (and hence to any destination) in a weighted graph with non-negative edge weights. It is a greedy algorithm.
Algorithm (source , destination ):
- For every vertex set
dist[v] = infinity,prev[v] = NULL, and mark it unvisited. Setdist[s] = 0. - Repeat while there are unvisited vertices:
- Select the unvisited vertex with the smallest
dist[u]; mark it visited. (If we may stop.) - For each neighbour of that is unvisited, let be the edge weight. If
dist[u] + w(u,v) < dist[v], setdist[v] = dist[u] + w(u,v)andprev[v] = u(relaxation).
- Select the unvisited vertex with the smallest
- The shortest distance to is
dist[t]. The path is found by followingprevfrom back to .
Pseudo-code:
Dijkstra(G, s):
for each vertex v: dist[v] = INF; prev[v] = NIL; visited[v] = false
dist[s] = 0
while some vertex is unvisited:
u = unvisited vertex with minimum dist
visited[u] = true
for each neighbour v of u:
if not visited[v] and dist[u] + w(u,v) < dist[v]:
dist[v] = dist[u] + w(u,v)
prev[v] = u
Complexity. With an adjacency matrix and a linear scan for the minimum: . With an adjacency list and a binary-heap priority queue: .
The algorithm fails if the graph has negative edge weights (use Bellman-Ford instead).
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 5 marks
Write a program to implement insertion sort.
Answer
Insertion sort builds the sorted array one element at a time. For each element (the key), it is compared with the elements before it, larger elements are shifted one place right, and the key is inserted in its correct position. Time complexity is in the worst and average cases and in the best case (already sorted); it is stable and in place.
#include <stdio.h>
void insertionSort(int a[], int n) {
for (int i = 1; i < n; i++) {
int key = a[i];
int j = i - 1;
while (j >= 0 && a[j] > key) {
a[j + 1] = a[j]; /* shift larger element right */
j--;
}
a[j + 1] = key; /* place the key */
}
}
int main() {
int a[100], n, i;
printf("Enter number of elements: ");
scanf("%d", &n);
printf("Enter %d elements:\n", n);
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
insertionSort(a, n);
printf("Sorted array: ");
for (i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2080 · 5 marks
Write short notes on:
a. Abstract data type
b. Circular linked list
Answer
(a) Abstract data type (ADT). An ADT is a mathematical model of a data structure that specifies the data it holds and the operations that can be performed on it, without saying how they are implemented. The user sees only the interface (what is done), while the implementation (how) is hidden, which gives abstraction and encapsulation. Examples: stack (push, pop, peek, isEmpty), queue (enqueue, dequeue), list, tree. The same ADT can have different implementations; for example, a stack can use an array or a linked list. Advantages are modularity, reusability, and the ability to change the implementation without changing the user's code.
(b) Circular linked list. A circular linked list is a linked list in which the last node points back to the first node instead of NULL, so the nodes form a ring and there is no NULL pointer. It can be singly circular (each node has next) or doubly circular (next and prev).
- A pointer to the last node (
tail) gives access to both ends:tail->nextis the head, so insertion at the front or end is . - Traversal starts from any node and stops when it returns to the start node.
- Advantages: any node can be reached from any other, and it suits round-robin scheduling, circular buffers and repeated cycling through a list.
- Disadvantage: careless traversal can loop forever, since there is no NULL end marker.
tail --> [C | * ] -> [A | * ] -> [B | * ] -+
^ |
+------------------------------+
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 10 marks
Define circular queue. How queue differ from stack. Write a program to implement linear queue.
Answer
Circular queue. A circular queue is a queue implemented on an array in which the last position is logically connected back to the first position, so the array behaves like a ring. After the rear reaches the last index, the next insertion goes to index 0 if that cell is free. Indices advance as . This removes the problem of a linear queue where freed cells at the front cannot be reused.
Queue vs stack.
| Queue | Stack |
|---|---|
| FIFO: First In First Out | LIFO: Last In First Out |
| Insertion at the rear, deletion at the front | Insertion and deletion both at the top |
| Two pointers: front and rear | One pointer: top |
| Operations: enqueue, dequeue | Operations: push, pop |
| The oldest element is removed first | The newest element is removed first |
| Uses: CPU scheduling, buffering, BFS | Uses: recursion, expression evaluation, DFS, undo |
Program for a linear queue (C).
#include <stdio.h>
#define MAX 5
int q[MAX], front = -1, rear = -1;
void enqueue(int x) {
if (rear == MAX - 1) { printf("Queue overflow\n"); return; }
if (front == -1) front = 0;
q[++rear] = x;
printf("%d inserted\n", x);
}
void dequeue() {
if (front == -1 || front > rear) { printf("Queue underflow\n"); return; }
printf("Deleted: %d\n", q[front++]);
}
void display() {
if (front == -1 || front > rear) { printf("Queue is empty\n"); return; }
printf("Queue: ");
for (int i = front; i <= rear; i++) printf("%d ", q[i]);
printf("\n");
}
int main() {
int choice, x;
do {
printf("\n1.Enqueue 2.Dequeue 3.Display 4.Exit\nChoice: ");
scanf("%d", &choice);
switch (choice) {
case 1: printf("Enter value: "); scanf("%d", &x); enqueue(x); break;
case 2: dequeue(); break;
case 3: display(); break;
case 4: break;
default: printf("Invalid choice\n");
}
} while (choice != 4);
return 0;
}
Enqueue and dequeue both take time.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 10 marks
What is AVL tree? How heap differ from tree? Construct an AVL tree for data 24,12,8,15,35,30,57,40,45 and 78.
Answer
AVL tree. An AVL tree is a self-balancing binary search tree in which, for every node, the balance factor is , or . When an insertion or deletion makes at some node, rotations (LL, RR, LR, RL) restore the balance. Its height is , so search, insert and delete take .
Heap vs tree (binary search tree).
| Heap | Binary search tree |
|---|---|
| A complete binary tree | Need not be complete; any shape |
| Ordering: each parent is (max-heap) or (min-heap) its children | Ordering: left subtree node right subtree |
| No ordering between siblings, so in-order traversal is not sorted | In-order traversal gives sorted keys |
| Finds the maximum or minimum in | Finds the minimum or maximum in |
| Search for an arbitrary key is | Search is , which is if balanced |
| Usually stored in an array | Usually stored with pointers |
| Used for priority queues and heap sort | Used for searching and ordered data |
Construction of the AVL tree for 24, 12, 8, 15, 35, 30, 57, 40, 45, 78.
- Insert 24, then 12 (left of 24), then 8 (left of 12). Node 24 has (LL case). A right rotation at 24 gives root 12 with children 8 and 24.
- Insert 15 (left of 24) and 35 (right of 24). The tree is 12 (8, 24(15, 35)) and is balanced.
- Insert 30 (left of 35). Node 12 has (RR case). A left rotation at 12 gives root 24 with left subtree 12(8, 15) and right subtree 35(30, -).
- Insert 57 (right of 35) and 40 (left of 57). Balanced.
- Insert 45 (right of 40). Node 57 has and its left child 40 is right-heavy (LR case). Rotate left at 40 and then right at 57: 45 becomes the subtree root with children 40 and 57. Now 35 has children 30 and 45(40, 57).
- Insert 78 (right of 57). Node 35 has and its right child 45 is right-heavy (RR case). A left rotation at 35 makes 45 the subtree root, with left child 35(30, 40) and right child 57(-, 78).
Final AVL tree
24
/ \
12 45
/ \ / \
8 15 35 57
/ \ \
30 40 78
All nodes satisfy , and the in-order traversal 8, 12, 15, 24, 30, 35, 40, 45, 57, 78 is sorted.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 5 marks
Explain big oh notation in brief. Find big oh of the following function:
f(x) = 5x^4 + 9x^2 + 7x + 9.
Answer
Big O notation. Big O gives an asymptotic upper bound on the growth rate of an algorithm's running time (or space) for large input size. It is used to describe the worst-case behaviour and ignores constant factors and lower-order terms.
Formally, if there exist positive constants and such that
So grows at least as fast as for large . Common orders are .
Big O of .
For we have , and , so
Hence for all , i.e. and satisfy the definition. Therefore
The leading term dominates; the coefficient 5 and the lower terms are ignored.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 5 marks
Convert the infix expression
A+(((B-C)*(D-E)+F)/G)$(H-I) into post expression using stack.
Answer
Convert to postfix using a stack.
Precedence (high to low): (exponent, right associative) > , > , . Rules: operands go straight to the output; an operator pops from the stack every operator of higher precedence (or equal precedence, for left-associative operators) before being pushed; ( is pushed; ) pops until the matching (.
| Symbol | Stack (bottom to top) | Postfix output |
|---|---|---|
| A | A | |
| + | + | A |
| ( | + ( | A |
| ( | + ( ( | A |
| ( | + ( ( ( | A |
| B | + ( ( ( | A B |
| - | + ( ( ( - | A B |
| C | + ( ( ( - | A B C |
| ) | + ( ( | A B C - |
| * | + ( ( * | A B C - |
| ( | + ( ( * ( | A B C - |
| D | + ( ( * ( | A B C - D |
| - | + ( ( * ( - | A B C - D |
| E | + ( ( * ( - | A B C - D E |
| ) | + ( ( * | A B C - D E - |
| + | + ( ( + | A B C - D E - * |
| F | + ( ( + | A B C - D E - * F |
| ) | + ( | A B C - D E - * F + |
| / | + ( / | A B C - D E - * F + |
| G | + ( / | A B C - D E - * F + G |
| ) | + | A B C - D E - * F + G / |
| $ | + $ | A B C - D E - * F + G / |
| ( | + $ ( | A B C - D E - * F + G / |
| H | + $ ( | A B C - D E - * F + G / H |
| - | + $ ( - | A B C - D E - * F + G / H |
| I | + $ ( - | A B C - D E - * F + G / H I |
| ) | + $ | A B C - D E - * F + G / H I - |
| end | (pop all) | A B C - D E - * F + G / H I - $ + |
(When + is read the first time the stack is empty, and when + inside the brackets is read it pops *, because * has higher precedence. The $ is pushed on + because it has higher precedence.)
Postfix expression:
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 5 marks
Write a program to find GCD of two numbers using recursion.
Answer
GCD using recursion (Euclid's algorithm). The GCD of and satisfies
#include <stdio.h>
int gcd(int a, int b) {
if (b == 0)
return a; /* base case */
return gcd(b, a % b); /* recursive case */
}
int main(void) {
int x, y;
printf("Enter two numbers: ");
scanf("%d %d", &x, &y);
printf("GCD of %d and %d is %d\n", x, y, gcd(x, y));
return 0;
}
Trace for : . So the output is GCD of 48 and 18 is 6.
The recursion terminates because the second argument strictly decreases at every call and finally becomes 0. The time complexity is .
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 5 marks
What is the application of spanning tree? Draw a MST of a graph containing any 8 vertices and 11 edges with arbitrary edge costs.
Answer
Spanning tree. A spanning tree of a connected graph with vertices is a subgraph that contains all the vertices, is connected and has no cycle, so it has exactly edges. In a weighted graph, the spanning tree with the least total edge cost is the minimum spanning tree (MST).
Applications of spanning trees:
- Designing least-cost networks: laying telephone, electrical, water, gas or computer network cables to connect all sites with minimum total length/cost.
- Network routing and broadcasting without loops (spanning tree protocol in Ethernet switches).
- Approximation algorithms for the travelling salesman problem and other routing problems.
- Cluster analysis, image segmentation and circuit design (connecting pins with minimum wire).
Example graph (8 vertices, 11 edges). Vertices A to H with edge costs:
AB = 4, AC = 8, BC = 11, BD = 9, CE = 7, CF = 1, DE = 2, DG = 7, EF = 6, FH = 2, GH = 4.
Kruskal's algorithm: sort the edges by cost and add an edge if it does not form a cycle.
| Edge | Cost | Decision |
|---|---|---|
| CF | 1 | accept |
| DE | 2 | accept |
| FH | 2 | accept |
| AB | 4 | accept |
| GH | 4 | accept |
| EF | 6 | accept (joins {D,E} with {C,F,H,G}) |
| CE | 7 | reject (C and E already connected, cycle) |
| DG | 7 | reject (cycle) |
| AC | 8 | accept (joins {A,B} with the rest; now 7 edges) |
| BD, BC | 9, 11 | reject |
The MST has edges: CF, DE, FH, AB, GH, EF, AC.
A --4-- B
|
8
|
C --1-- F --2-- H --4-- G
|
6
|
E --2-- D
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 5 marks
Sort the number {82, 73, 12, 39, 26, 88, 2, 9, 60, 41} using shell sort.
Answer
Shell sort sorts elements that are a gap apart using insertion sort, then reduces the gap until it is 1. For 10 elements take gaps .
Original: 82, 73, 12, 39, 26, 88, 2, 9, 60, 41 (positions 0 to 9)
Pass 1, gap = 5. Sublists (positions and ): (82, 88), (73, 2), (12, 9), (39, 60), (26, 41). Sorting each pair gives (82, 88), (2, 73), (9, 12), (39, 60), (26, 41).
After pass 1: 82, 2, 9, 39, 26, 88, 73, 12, 60, 41
Pass 2, gap = 2. Sublist of even positions: 82, 9, 26, 73, 60, which sorts to 9, 26, 60, 73, 82. Sublist of odd positions: 2, 39, 88, 12, 41, which sorts to 2, 12, 39, 41, 88.
After pass 2: 9, 2, 26, 12, 60, 39, 73, 41, 82, 88
Pass 3, gap = 1 (ordinary insertion sort on the nearly sorted list):
- 2 moves before 9: 2, 9, 26, 12, 60, 39, 73, 41, 82, 88
- 12 moves before 26: 2, 9, 12, 26, 60, 39, 73, 41, 82, 88
- 39 moves before 60: 2, 9, 12, 26, 39, 60, 73, 41, 82, 88
- 41 moves before 60: 2, 9, 12, 26, 39, 41, 60, 73, 82, 88
Sorted list: 2, 9, 12, 26, 39, 41, 60, 73, 82, 88
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 5 marks
What is hashing? how do you apply linear probing and rehashing explain with example.
Answer
Hashing. Hashing is a technique to store and retrieve records directly using a hash function that maps a key to an index (address) in a hash table, giving average search, insertion and deletion. A common function is , where is the table size (preferably prime). When two different keys map to the same index, a collision occurs and must be resolved.
Linear probing (open addressing). If the slot is occupied, probe the next slots sequentially (wrapping round) until an empty one is found:
Example: , , insert 50, 700, 76, 85, 92, 73, 101.
| Key | h(k) | Probes | Placed at |
|---|---|---|---|
| 50 | 0 | 0 free | 0 |
| 700 | 0 | 0 full, 1 free | 1 |
| 76 | 6 | free | 6 |
| 85 | 5 | free | 5 |
| 92 | 2 | free | 2 |
| 73 | 3 | free | 3 |
| 101 | 1 | 1, 2, 3 full, 4 free | 4 |
Table: index 0 = 50, 1 = 700, 2 = 92, 3 = 73, 4 = 101, 5 = 85, 6 = 76, 7 to 9 empty.
Disadvantage: primary clustering, long runs of occupied slots form and make probing slower. Search follows the same probe sequence until the key or an empty slot is found.
Rehashing. Rehashing is used when the table becomes too full (load factor exceeds about 0.5 to 0.7), so that probe sequences become long or insertion fails. A new table about twice as large (next prime number) is created, and every existing key is re-inserted by applying the new hash function . (The term is also used for applying a second hash function when a collision occurs, as in double hashing .)
Example: table size holding 13, 15, 6, 24 using linear probing: 13 goes to 6, 15 to 1, 6 collides at 6 and goes to 0, 24 goes to 3. Load factor , so rehash into (next prime above 14):
13 mod 17 = 13, 15 mod 17 = 15, 6 mod 17 = 6, 24 mod 17 = 7.
All keys now sit at their home slots without collision. Rehashing costs but happens rarely, so insertion remains cheap on average.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 5 marks
What is the algorithm for node insertion and deletion from specified position from doubly linked list.
Answer
A doubly linked list node has a data field and two pointers, prev and next.
struct node {
int data;
struct node *prev, *next;
};
head points to the first node. Positions are counted from 1.
Insertion at position pos (new element x)
- Create a new node
new; if memory is not available, report overflow. new->data = x- If
pos == 1(insertion at the beginning):new->prev = NULL;new->next = head- if
head != NULL,head->prev = new head = new; stop.
- Otherwise set
temp = headand move it forwardpos - 2times (tempis now the node after which the new node goes); iftempbecomesNULL, the position is invalid. new->next = temp->nextnew->prev = temp- If
temp->next != NULL,temp->next->prev = new temp->next = new- Stop.
void insert_at(int x, int pos) {
struct node *new = malloc(sizeof(struct node)), *t = head;
new->data = x;
if (pos == 1) {
new->prev = NULL; new->next = head;
if (head) head->prev = new;
head = new; return;
}
for (int i = 1; i < pos - 1 && t != NULL; i++) t = t->next;
if (t == NULL) { printf("Invalid position\n"); free(new); return; }
new->next = t->next;
new->prev = t;
if (t->next) t->next->prev = new;
t->next = new;
}
Deletion from position pos
- If
head == NULL, report underflow and stop. - Set
temp = head. - If
pos == 1:head = temp->next; ifhead != NULL,head->prev = NULL;free(temp); stop. - Otherwise move
tempforwardpos - 1times; iftempbecomesNULL, the position is invalid. temp->prev->next = temp->next- If
temp->next != NULL,temp->next->prev = temp->prev free(temp); stop.
void delete_at(int pos) {
struct node *t = head;
if (head == NULL) { printf("Underflow\n"); return; }
for (int i = 1; i < pos && t != NULL; i++) t = t->next;
if (t == NULL) { printf("Invalid position\n"); return; }
if (t->prev) t->prev->next = t->next; else head = t->next;
if (t->next) t->next->prev = t->prev;
free(t);
}
Both operations need time to reach the position, but the actual relinking takes constant time, and no previous-node pointer has to be tracked during deletion because each node holds its own prev pointer.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 5 marks
What is linear queue? Why do we need circular queue? Explain.
Answer
Linear queue. A queue is a FIFO linear data structure: elements are inserted at the rear and deleted from the front. In an array implementation of size , front and rear start at (or 0); enqueue increments rear and stores the item (overflow when rear == N-1); dequeue removes the item at front and increments front (underflow when the queue is empty).
void enqueue(int x) {
if (rear == N - 1) { printf("Overflow\n"); return; }
if (front == -1) front = 0;
q[++rear] = x;
}
int dequeue(void) {
if (front == -1 || front > rear) { printf("Underflow\n"); return -1; }
return q[front++];
}
Why a circular queue is needed. In a linear queue, positions freed by dequeue at the front can never be reused. For example, with , enqueue A, B, C, D, E (rear = 4), then dequeue twice (front = 2). The queue holds only 3 elements, but rear == N-1, so it reports overflow although two slots (0 and 1) are empty. Space is wasted, and the only way out is to shift all elements left, which costs .
A circular queue treats the array as a ring: after the last index, rear (and front) wrap round to index 0 using modular arithmetic:
The queue is full when and empty when front == -1 (or front == rear in the variant that keeps one slot unused).
void enqueue(int x) {
if ((rear + 1) % N == front) { printf("Overflow\n"); return; }
if (front == -1) front = 0;
rear = (rear + 1) % N;
q[rear] = x;
}
int dequeue(void) {
if (front == -1) { printf("Underflow\n"); return -1; }
int x = q[front];
if (front == rear) front = rear = -1; /* last element removed */
else front = (front + 1) % N;
return x;
}
In the example above, the next enqueue places the item at index 0, so all slots can be used. Advantages: efficient use of memory, both operations take time, and no shifting is needed. It is used in CPU scheduling, buffering (keyboard, printer spooling) and traffic systems.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
- 2081 · 5 marks
Write short notes on:
- Breadth First traversal of graph
- TOH
Answer
Breadth First traversal (BFS) of a graph. BFS visits the start vertex, then all its adjacent (unvisited) vertices, then all vertices at distance 2, and so on, i.e. level by level. A queue is used to remember the vertices whose neighbours are still to be explored, and a visited array prevents revisiting.
Algorithm BFS(G, s):
- Mark
svisited and enqueues. - While the queue is not empty:
- dequeue a vertex
vand process (print) it; - for every neighbour
wofvthat is not visited, markwvisited and enqueuew.
- dequeue a vertex
- Stop.
Example: for edges A-B, A-C, B-D, C-D, C-E starting at A: queue A; visit A, enqueue B, C; visit B, enqueue D; visit C, enqueue E; visit D; visit E. Traversal order: A B C D E.
Time complexity is with an adjacency list ( with a matrix). Uses: shortest path in unweighted graphs, finding connected components, level-order traversal, web crawling and peer-to-peer network broadcasting.
Tower of Hanoi (TOH). There are three pegs (source A, auxiliary B, destination C) and disks of different sizes stacked on A with the largest at the bottom. The task is to move all disks to C, moving one disk at a time and never placing a larger disk on a smaller one.
Recursive solution for disks:
- Move the top disks from A to B (using C).
- Move the largest disk from A to C.
- Move the disks from B to C (using A).
void toh(int n, char from, char to, char aux) {
if (n == 0) return;
toh(n - 1, from, aux, to);
printf("Move disk %d from %c to %c\n", n, from, to);
toh(n - 1, aux, to, from);
}
The number of moves satisfies , , giving
For (7 moves): 1: A to C, 2: A to B, 1: C to B, 3: A to C, 1: B to A, 2: B to C, 1: A to C. TOH is a classic example of recursion.
Answer checked by Claude Sonnet · Oct 21, 2026
Test yourself · 2 MCQs
Loading…
Questions from TU BSc CSIT 2075 Third Semester Numerical Method (TU IOST board exam, 2075), TU BSc CSIT 2077 Third Semester Numerical Method (TU IOST board exam, 2077), TU BSc CSIT 2078 Third Semester Numerical Method (TU IOST board exam, 2078), TU BSc CSIT 2079 Third Semester Numerical Method (TU IOST board exam, 2079), TU BSc CSIT 2080 Third Semester Numerical Method (TU IOST board exam, 2080), TU BSc CSIT 2081 Third Semester Numerical Method (TU IOST board exam, 2081), TU BSc CSIT 2075 Third Semester Computer Architecture (TU IOST board exam, 2075), TU BSc CSIT 2077 Third Semester Computer Architecture (TU IOST board exam, 2077), TU BSc CSIT 2078 Third Semester Computer Architecture (TU IOST board exam, 2078), TU BSc CSIT 2079 Third Semester Computer Architecture (TU IOST board exam, 2079), TU BSc CSIT 2080 Third Semester Computer Architecture (TU IOST board exam, 2080), TU BSc CSIT 2081 Third Semester Computer Architecture (TU IOST board exam, 2081), TU BSc CSIT 2075 Third Semester Computer Graphics (TU IOST board exam, 2075), TU BSc CSIT 2077 Third Semester Computer Graphics (TU IOST board exam, 2077), TU BSc CSIT 2078 Third Semester Computer Graphics (TU IOST board exam, 2078), TU BSc CSIT 2079 Third Semester Computer Graphics (TU IOST board exam, 2079), TU BSc CSIT 2080 Third Semester Computer Graphics (TU IOST board exam, 2080), TU BSc CSIT 2081 Third Semester Computer Graphics (TU IOST board exam, 2081), TU BSc CSIT 2082 Third Semester Computer Graphics (TU IOST board exam, 2082), TU BSc CSIT 2074 Third Semester Data Structures and Algorithms (TU IOST board exam, 2074), TU BSc CSIT 2075 Third Semester Data Structures and Algorithms (TU IOST board exam, 2075), TU BSc CSIT 2077 Third Semester Data Structures and Algorithms (TU IOST board exam, 2077), TU BSc CSIT 2078 Third Semester Data Structures and Algorithms (TU IOST board exam, 2078), TU BSc CSIT 2079 Third Semester Data Structures and Algorithms (TU IOST board exam, 2079), TU BSc CSIT 2080 Third Semester Data Structures and Algorithms (TU IOST board exam, 2080), TU BSc CSIT 2081 Third Semester Data Structures and Algorithms (TU IOST board exam, 2081), TU BSc CSIT 2075 Third Semester Statistics II (TU IOST board exam, 2075), TU BSc CSIT 2077 Third Semester Statistics II (TU IOST board exam, 2077), TU BSc CSIT 2078 Third Semester Statistics II (TU IOST board exam, 2078), TU BSc CSIT 2079 Third Semester Statistics II (TU IOST board exam, 2079), TU BSc CSIT 2080 Third Semester Statistics II (TU IOST board exam, 2080), TU BSc CSIT 2081 Third Semester Statistics II (TU IOST board exam, 2081) and TU BSc CSIT 2082 Third Semester Statistics II (TU IOST board exam, 2082). Answers are written for this site; check them against your class notes.