0% found this document useful (0 votes)
30 views40 pages

PUT Sol

The document outlines various concepts in data structures and algorithms, including differences between linear and non-linear data structures, tail recursion, internal vs external sorting, and the characteristics of binary search trees and heaps. It also discusses collision resolution techniques in hashing, the conditions under which a graph becomes a tree, and provides algorithms for sorting and data manipulation tasks like heap sort and merge sort. Additionally, it includes examples of B-trees and graph representation with the Floyd-Warshall algorithm.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views40 pages

PUT Sol

The document outlines various concepts in data structures and algorithms, including differences between linear and non-linear data structures, tail recursion, internal vs external sorting, and the characteristics of binary search trees and heaps. It also discusses collision resolution techniques in hashing, the conditions under which a graph becomes a tree, and provides algorithms for sorting and data manipulation tasks like heap sort and merge sort. Additionally, it includes examples of B-trees and graph representation with the Floyd-Warshall algorithm.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

Section A

Q1 a)Difference between Linear and Non-linear Data Structures:

S.NO Linear Data Structure Non-linear Data Structure

In a linear data structure, data elements


In a non-linear data structure, data
are arranged in a linear order where
1. elements are attached in hierarchically
each and every element is attached to
manner.
its previous and next adjacent.

In linear data structure, single level is Whereas in non-linear data structure,


2.
involved. multiple levels are involved.

Its implementation is easy in


While its implementation is complex in
3. comparison to non-linear data
comparison to linear data structure.
structure.

While in non-linear data structure, data


In linear data structure, data elements
4. elements can’t be traversed in a single run
can be traversed in a single run only.
only.

While in a non-linear data structure,


In a linear data structure, memory is
5. memory is utilized in an efficient way.
not utilized in an efficient way.

Its examples are: array, stack, queue,


6. While its examples are: trees and graphs.
linked list, etc.

Applications of linear data structures Applications of non-linear data structures


7. are mainly in application software are in Artificial Intelligence and image
development. processing.

Non-linear data structures are useful for


representing complex relationships and
Linear data structures are useful for
8. data hierarchies, such as in social
simple data storage and manipulation.
networks, file systems, or computer
networks.

Q1 b)(C04): WHAT DO YOU UNDERSTAND BY TAIL RECURSION?


ANS) Tail recursion is defined as a recursive function in which the recursive call is the last
statement that is executed by the function. So basically nothing is left to execute after the
recursion call.

Tail recursion is defined as a recursive function in which the recursive call is the last statement
that is executed by the function. So basically nothing is left to execute after the recursion call.

EXAMPLE

Recursion is applied to problems (situations) where you can break it up (reduce it) into smaller parts,
and each part(s) looks similar to the original problem. Good examples of where things that contain
smaller parts similar to itself are: tree structure (a branch is like a tree) lists (part of a list is still a list)

Q1 c) Difference between internal sorting and external sorting

Comparison Table:

Feature Internal Sorting External Sorting

Data Size Small (fits in RAM) Large (exceeds RAM capacity)

Storage Used RAM Disk or External Storage

Speed Faster (only memory access) Slower (due to disk I/O)

Complexity Less complex More complex (merging needed)

External Merge Sort, Multiway


Merge Sort
Examples Quick Sort, Merge Sort

Q1 d)Convert the infix expression (a+b) *(c-d) /e*f to postfix. Give the
answer without any spaces
0((
1A(A
2+(+A
3B(+AB
4)AB+
5**AB+
6(*(AB+
7C*(AB+C
8-*(-AB+C
9D*(-AB+CD
10 ) * A B + C D -
11 / / A B + C D - *
12 E / A B + C D - * E
13 * * A B + C D - * E /
14 F * A B + C D - * E / F
15 A B + C D - * E / F *

Q1 e)Difference between binary search tree and heap with example

Binary Search Tree


Feature Heap
(BST)
Structure Binary tree (sorted) Complete binary tree
Parent > Children (Max Heap) or Parent < Children
Ordering Left < Root < Right
(Min Heap)
Search
O(log n) (average) O(n) (unsorted structure)
Time
Insertion O(log n) O(log n) (heapify)
Deletion O(log n) O(log n) (remove root, heapify)
Use Case Searching, sorted data Priority Queue, Heap Sort

Q1 f) Difference between linear and Quadratic probing techniques of collision in


hashing with example
Linear probing and quadratic probing are both methods for finding an open
slot in a hash table. Linear probing searches sequentially, while quadratic
probing searches in a more spaced-out manner.

Feature Linear Probing Quadratic Probing


Probing Sequence iii (1, 2, 3, 4...) i2i^2i2 (1, 4, 9, 16...)
Feature Linear Probing Quadratic Probing
Primary Clustering High Low
Secondary Clustering Present Present but less severe
Performance Slower if many collisions occur Better than linear probing
Best Use Case Small hash tables Larger tables with fewer collisions

Q1 g) When does graph become a tree


A tree is an undirected graph G that satisfies any of the following equivalent
conditions: G is connected and acyclic (contains no cycles). G is acyclic, and a simple
cycle is formed if any edge is added to G. G is connected, but would become
disconnected if any single edge is removed from G.

Section B

Q2 a)i) Explain asymptotic notation . Define big-oh notation and find the
complexity of the following recursive function T(n)= 4T(n/2) +n logn.

Asymptotic Notation

Asymptotic notation is a mathematical way to describe the running time (complexity) of an


algorithm in terms of input size (n). It helps analyze how an algorithm's performance grows as
the input size increases.

Types of Asymptotic Notations:

1. Big-O Notation (O) → Upper bound (worst-case performance).


2. Omega Notation (Ω) → Lower bound (best-case performance).
3. Theta Notation (Θ) → Tight bound (average-case performance).

Big-O Notation (O)

Big-O notation represents the worst-case time complexity of an algorithm. It provides an upper
bound on the execution time in terms of input size n.

Mathematical Definition:

An algorithm is O(f(n)) if there exist constants c > 0 and n₀ such that:

T(n)≤c⋅f(n)for all n≥n0T(n) \leq c \cdot f(n) \quad \text{for all } n \geq
n₀T(n)≤c⋅f(n)for all n≥n0
where:

 T(n) is the actual running time of the algorithm.


 f(n) is a function representing the worst-case complexity.
 c is a constant multiplier.
 n₀ is a threshold input size beyond which the complexity holds true.

Q2 a)ii) Write an algorithm to insert a node at the end in a circular linked list
Insertion at the end in circular linked list

Algorithm
o Step 1: IF PTR = NULL
Write OVERFLOW
Go to Step 1
[END OF IF]
o Step 2: SET NEW_NODE = PTR
o Step 3: SET PTR = PTR -> NEXT
o Step 4: SET NEW_NODE -> DATA = VAL
o Step 5: SET NEW_NODE -> NEXT = HEAD
o Step 6: SET TEMP = HEAD
o Step 7: Repeat Step 8 while TEMP -> NEXT != HEAD
o Step 8: SET TEMP = TEMP -> NEXT
[END OF LOOP]

o Step 9: SET TEMP -> NEXT = NEW_NODE


o Step 10: EXIT

Q2 b) i) Write an algorithm for finding solution to the tower of hanoi problem

START

Procedure Hanoi(disk, source, dest, aux)

IF disk == 1, THEN

move disk from source to dest

ELSE Hanoi(disk - 1, source, aux, dest) //

Step 1 move disk from source to dest //

Step 2 Hanoi(disk - 1, aux, dest, source) //

Step 3 END IF

END Procedure

STOP

Tower of Hanoi Algorithm (4 Discs) – Step-by-Step Explanation

The Tower of Hanoi is a mathematical puzzle involving three pegs (A, B, and C) and multiple
discs of different sizes. The objective is to move all the discs from the source peg (A) to the
destination peg (C) using an auxiliary peg (B) while following these rules:

1. Only one disc can be moved at a time.


2. A disc can only be placed on top of a larger disc or on an empty peg.
3. The goal is to move all discs in the fewest moves possible.

Recursive Algorithm
For n discs:

1. Move n-1 discs from A to B using C as auxiliary.


2. Move the nth (largest) disc from A to C.
3. Move n-1 discs from B to C using A as auxiliary.

For 4 discs, the minimum moves required are:

24−1=152^4 - 1 = 1524−1=15

Step-by-Step Solution for 4 Discs

Initial Configuration

A: 4 3 2 1 (Source)

B: - (Auxiliary)

C: - (Destination)

Moves

1. Move Disc 1 from A → C


2. Move Disc 2 from A → B
3. Move Disc 1 from C → B
4. Move Disc 3 from A → C
5. Move Disc 1 from B → A
6. Move Disc 2 from B → C
7. Move Disc 1 from A → C
8. Move Disc 4 from A → B
9. Move Disc 1 from C → B
10. Move Disc 2 from C → A
11. Move Disc 1 from B → A
12. Move Disc 3 from C → B
13. Move Disc 1 from A → C
14. Move Disc 2 from A → B
15. Move Disc 1 from C → B

Final Configuration

A: - (Source)
B: 4 3 2 1 (Destination)

C: - (Auxiliary)

Q2 c)i) Write an algorithm of heap sort

A heap is a complete binary tree, and the binary tree is a tree in which the node can have
the utmost two children. A complete binary tree is a binary tree in which all the levels except
the last level, i.e., leaf node, should be completely filled, and all the nodes should be left-
justified.

Algorithm
1. HeapSort(arr)
2. BuildMaxHeap(arr)
3. for i = length(arr) to 2
4. swap arr[1] with arr[i]
5. heap_size[arr] = heap_size[arr] ? 1
6. MaxHeapify(arr,1)
7. End
Q2 c)ii) Write an algorithm of merge sort

1. MERGE_SORT(arr, beg, end)


2.
3. if beg < end
4. set mid = (beg + end)/2
5. MERGE_SORT(arr, beg, mid)
6. MERGE_SORT(arr, mid + 1, end)
7. MERGE (arr, beg, mid, end)
8. end of if
9.
10. END MERGE_SORT
Q2 d) i) Inserting Keys into a B-Tree of Order 5

A B-tree of order 5 follows these properties:

1. Each node can have at most 4 keys and 5 children.


2. Each node (except root) must have at least ⌈ m/2⌉ children → i.e., at least 3 children for a non-
root node.
3. Keys in a node are arranged in sorted order.
4. Splitting occurs when a node overflows (i.e., has more than 4 keys), and the middle key moves
up.

Step 1: Insert First Four Keys

Insert a, g, f, b into a single node. Arrange them in sorted order:

[a b f g]

No splitting is needed.

Step 2: Insert Key k

[ a b f g k ]

Now the node is full.

Step 3: Insert d (Overflow Occurs)

Since the node is full, we split it at the middle key (f).

 Middle key f moves up and becomes the root.


 Left child gets [ a b d ]
 Right child gets [ g k ]

[ f ]

/ \

[ a b d ] [ g k ]

Step 4: Insert h, m, j, e

 h goes to the right child [ g h k ]


 m goes to the right child [ g h k m ]
 j goes to the right child [ g h j k m ] (Full node)
 e goes to the left child [ a b d e ] (No splitting needed)

Since [ g h j k m ] overflows, split at j:

 j moves up
 Left child becomes [ g h ]
 Right child becomes [ k m ]

[ f j ]

/ | \

[ a b d e ] [ g h ] [ k m ]

Step 5: Insert s, i, r, x

 s goes to the rightmost [ k m s ]


 i goes to [ g h i ]
 r goes to [ k m s r ] (Sorted: [ k m r s ])
 x goes to [ k m r s x ] (Full node, Split at r)

Since [ k m r s x ] overflows:

 r moves up.
 Left child [ k m ]
 Right child [ s x ]

[ f j r ]

/ | | \

[ a b d e ] [ g h i ] [ k m ] [ s x ]

Step 6: Insert c, l, n, t, u, p

 c goes to [ a b c d e ] (Full node, Split at c)


 l goes to [ k l m ]
 n goes to [ k l m n ]
 t goes to [ s t x ]
 u goes to [ s t u x ]
 p goes to [ n p ]

Splitting [ a b c d e ] at c:
 c moves up.
 Left [ a b ]
 Right [ d e ]

Since f j r is full after c moves up, split at j:

 j moves up.
 New root: [ j ]
 Left child [ c f ]
 Right child [ r ]

[ j ]

/ \

[ c f ] [ r ]

/ | \ / \

[ a b ] [ d e ] [ g h i ] [ k l m n p ] [ s t u x ]

Final B-Tree Structure

[ j ]

/ \

[ c f ] [ r ]

/ | \ / \

[ a b ] [ d e ] [ g h i ] [ k l m n p ] [ s t u x ]

Q2 d) ii) if the Inoder sequence of a binary tree is B,I,D,A,CG,E,H,F and Postorder sequence is

I,D,B,G,C,H,F,E,A .
Q2 e)i) Given Graph Representation

The given graph has 4 vertices (1, 2, 3, 4) with weighted edges:

FromTo Weight

1 → 23

1 → 45

2 → 12

2 → 44

3→ 2 1

4 → 32

Step 1: Initialize the Distance Matrix


i j
We start by creating the initial distance matrix dist, where dist[i][j] represents the shortest distance from vertex i to vertex j . If

there is no direct edge, we use infinity (INF).

1 2 3 4

1 0 3 INF 5

2 2 0 INF 4

3 INF 1 0 INF

4 INF INF 2 0

Step 2: Apply the Floyd-Warshall Algorithm


We will now iteratively update the distance matrix by considering each vertex as an intermediate point.

Iteration 1: k=1 k=1 (Using vertex 1 as intermediate)

Update paths that can be improved by going through vertex 1.

1 2 3 4

1 0 3 INF 5

2 2 0 INF 4

3 INF 1 0 INF

4 INF INF 2 0

No changes are needed in this iteration.

Iteration 2: k=2 k=2 (Using vertex 2 as intermediate)

Update paths that can be improved by going through vertex 2.

1 2 3 4

1 0 3 INF 5

2 2 0 INF 4

3 3 1 0 5
4 INF INF 2 0

The path from 3 to 1 is updated to 3 (via 2).


The path from 3 to 4 is updated to 5 (via 2).

Iteration 3: k=3 k=3 (Using vertex 3 as intermediate)

Update paths that can be improved by going through vertex 3.

1 2 3 4

1 0 3 INF 5

2 2 0 INF 4

3 3 1 0 5

4 5 3 2 0

The path from 4 to 1 is updated to 5 (via 3).


The path from 4 to 2 is updated to 3 (via 3).

Iteration 4: k=4 k=4 (Using vertex 4 as intermediate)

Update paths that can be improved by going through vertex 4.

1 2 3 4

1 0 3 7 5

2 2 0 6 4

3 3 1 0 5

4 5 3 2 0

The path from 1 to 3 is updated to 7 (via 4).


The path from 2 to 3 is updated to 6 (via 4).

Final Distance Matrix:


The final distance matrix after applying the Floyd-Warshall algorithm is:

1 2 3 4
1 0 3 7 5

2 2 0 6 4

3 3 1 0 5

4 5 3 2 0

Interpretation:
The shortest path from vertex 1 to vertex 3 is 7.
The shortest path from vertex 2 to vertex 3 is 6.
The shortest path from vertex 4 to vertex 1 is 5.

Q2 d)ii) Difference Between DFS and BFS

Feature Depth First Search (DFS) Breadth First Search (BFS)

Explores as far as possible Explores all neighbor nodes at


Definition along each branch before the present depth before moving
backtracking. deeper.

Data
Uses Stack (or recursion). Uses Queue.
Structure

Traversal Goes deep first, then Visits all neighbors level by


Order backtracks. level.

Time
O(V + E) O(V + E)
Complexity

Space O(V) (due to recursion/stack


O(V) (due to queue storage).
Complexity usage).

Path Does not guarantee the shortest Guarantees the shortest path in
Finding path in unweighted graphs. an unweighted graph.

Used in topological sorting, Used in shortest path algorithms


Use Cases cycle detection, and (like unweighted graphs) and
backtracking problems. network broadcasting.
DFS (Depth-First Search) and BFS (Breadth-First Search) are two fundamental graph traversal algorithms that differ in their
exploration strategy and resulting tree structures.

Evidence Analysis

1.
DFS Characteristics:

2.
 Explores as far as possible along each branch before backtracking

 Uses a stack data structure (or recursion)

 Goes deep before going wide

 Path: 1→2→4→8→5→7→9→6→3

3.
BFS Characteristics:

4.
 Explores all vertices at the present depth before moving to vertices at the next depth level

 Uses a queue data structure

 Goes wide before going deep

 Path: 1→2→3→5→4→6→7→8→9

1.
BFS Tree for the Given Graph:

/|\

2 3 5

/ /\

4 6 7

| /\

8 9 8

Q3 a) (i) Find the Length of Each Dimension and Number of Elements in X and Y

The given arrays are:

 X(-2:2, 2:22) → The first dimension ranges from -2 to 2, and the second dimension from 2 to
22.
 Y(1:8, -5:5) → The first dimension ranges from 1 to 8, and the second from -5 to 5.

Length of Each Dimension

1.

For X:

2.

o First dimension: 2 - (-2) + 1 = 5


o Second dimension: 22 - 2 + 1 = 21
o Total Elements in X = 5 × 21 = 105

3.

For Y:

4.

o First dimension: 8 - 1 + 1 = 8
o Second dimension: 5 - (-5) + 1 = 11
o Total Elements in Y = 8 × 11 = 88

(ii) Find the Address of Element Y(2,2)

Given:

 Base Address of Y = 400


 Each element occupies 4 memory locations
 Row-major order addressing is used

Formula for Address Calculation (Row-Major Order)

Address(i,j)=Base Address+((i−L1)×N2+(j−L2))×Element Size\text{Address}(i,


j) = \text{Base Address} + \left( (i - L_1) \times N_2 + (j - L_2) \right)
\times \text{Element Size}Address(i,j)=Base Address+((i−L1)×N2+(j−L2
))×Element Size

where:

 L1 = 1 (Lower bound of first dimension)


 L2 = -5 (Lower bound of second dimension)
 N2 = 11 (Number of columns)
 Element size = 4
 (i, j) = (2, 2)

Substituting Values

Offset=(2−1)×11+(2−(−5))\text{Offset} = (2 - 1) \times 11 + (2 - (-
5))Offset=(2−1)×11+(2−(−5)) =(1×11)+(2+5)=11+7=18= (1 \times 11) + (2 + 5) =
11 + 7 = 18=(1×11)+(2+5)=11+7=18 Address=400+(18×4)=400+72=472\text{Address}
= 400 + (18 \times 4) = 400 + 72 = 472Address=400+(18×4)=400+72=472

Final Answer: The address of Y(2,2) is 472.

Q3 b) How to represent the polynomial using linked list

polynomial can be represented as a linked list where:

 Each node contains two parts:


1. Coefficient (coefcoefcoef)
2. Exponent (expexpexp)
 The nodes are stored in descending order of exponents.
 The next pointer points to the next term in the polynomia
 4x3+3x2+5x+6
 It is represented as:
Example : 4x3+3x2+5x+6

Coefficient Exponent
4 3
3 2
5 1
6 0

C program for adding two polynomials using linked list

// C program to add two polynomials


#include <stdio.h>
#include <stdlib.h>
struct Node {
int coeff;
int pow;
struct Node* next;
};

struct Node* createNode(int c, int p);

struct Node* addPolynomial(struct Node* head1, struct Node* head2) {

if (head1 == NULL) return head2;


if (head2 == NULL) return head1;

if (head1->pow > head2->pow) {


struct Node* nextPtr =
addPolynomial(head1->next, head2);
head1->next = nextPtr;
return head1;
}

else if (head1->pow < head2->pow) {


struct Node* nextPtr =
addPolynomial(head1, head2->next);
head2->next = nextPtr;
return head2;
}

// else store the sum of head1.coeff and head2.coeff in


// head1->coeff, then find its next node and return head1.
struct Node* nextPtr =
addPolynomial(head1->next, head2->next);
head1->coeff += head2->coeff;
head1->next = nextPtr;
return head1;
}

void printList(struct Node* head) {


struct Node* curr = head;

while (curr != NULL) {


printf("%d,%d ", curr->coeff, curr->pow);
curr = curr->next;
}

printf("\n");
}

struct Node* createNode(int c, int p) {


struct Node* newNode =
(struct Node*)malloc(sizeof(struct Node));
newNode->coeff = c;
newNode->pow = p;
newNode->next = NULL;
return newNode;
}

int main() {

// 1st polynomial: 5x^2+4x^1+2x^0


struct Node* head1 = createNode(5, 2);
head1->next = createNode(4, 1);
head1->next->next = createNode(2, 0);

// 2nd polynomial: -5x^1-5x^0


struct Node* head2 = createNode(-5, 1);
head2->next = createNode(-5, 0);

struct Node* head = addPolynomial(head1, head2);

printList(head);

return 0;
}

Q4a) Solution for (a) CO1

Convert Infix Expression to Reverse Polish Notation (RPN)

The given infix expression is:

x=−b+(b2−4ac)x = -b + \sqrt{(b^2 - 4ac)}x=−b+(b2−4ac)

We need to convert this to Reverse Polish Notation (Postfix Notation) using a stack-based
algorithm.

Step-by-Step Conversion
1. Identify Operators and Operands
1. Operators: +, -, ^, √
2. Operands: b, 4, a, c
2. Follow Operator Precedence

1.Exponentiation (^) has highest precedence.


2.Multiplication (*) follows.
3.Square root (√) is a function (applies to everything inside).
4.Addition (+) is last.
3. Convert Step-by-Step

1. b^2 → b 2 ^
2. 4ac → 4 a * c *
3. b^2 - 4ac → b 2 ^ 4 a * c * -
4. √(b^2 - 4ac) → b 2 ^ 4 a * c * - √
5. -b → b -
6. -b + √(b^2 - 4ac) → b - b 2 ^ 4 a * c * - √ +

Final Postfix Expression

b−b24a∗c∗−√+b - b 2 ^ 4 a * c * - √ +b−b24a∗c∗−√+

Q4b) Solution for (b) CO1

(i) Design a Method for Two Stacks in a Single Array

To efficiently manage two stacks within a single array, we place:

 Stack1 (Left to Right)


 Stack2 (Right to Left)

Implementation Idea:

 Use a single array of size N.


 Stack1 starts from index 0 and grows right.
 Stack2 starts from index N-1 and grows left.
 Prevent overflow until the array is completely full.

Algorithm for Push and Pop:

1. Push Operation:
o push1(value): Insert at top1++.
o push2(value): Insert at top2--.
o Check if top1 and top2 cross to prevent overflow.

2. Pop Operation:

o pop1(): Remove from top1--.


o pop2(): Remove from top2++.

C Code Implementation:

#include <stdio.h>#include <stdlib.h>

#define MAX 100

struct TwoStacks {

int arr[MAX];

int top1, top2;

};

// Initialize two stacksvoid init(struct TwoStacks* ts) {

ts->top1 = -1;

ts->top2 = MAX;

// Push to Stack 1void push1(struct TwoStacks* ts, int val) {

if (ts->top1 < ts->top2 - 1) {

ts->arr[++ts->top1] = val;

} else {

printf("Stack Overflow\n");

}
// Push to Stack 2void push2(struct TwoStacks* ts, int val) {

if (ts->top1 < ts->top2 - 1) {

ts->arr[--ts->top2] = val;

} else {

printf("Stack Overflow\n");

// Pop from Stack 1int pop1(struct TwoStacks* ts) {

if (ts->top1 >= 0) {

return ts->arr[ts->top1--];

} else {

printf("Stack Underflow\n");

return -1;

// Pop from Stack 2int pop2(struct TwoStacks* ts) {

if (ts->top2 < MAX) {

return ts->arr[ts->top2++];

} else {

printf("Stack Underflow\n");

return -1;

}
// Main functionint main() {

struct TwoStacks ts;

init(&ts);

push1(&ts, 10);

push2(&ts, 20);

push1(&ts, 30);

push2(&ts, 40);

printf("Popped from Stack 1: %d\n", pop1(&ts));

printf("Popped from Stack 2: %d\n", pop2(&ts));

return 0;

(ii) C Program to Reverse a String Using Stack

#include <stdio.h>#include <string.h>

#define MAX 100

// Stack structurestruct Stack {

int top;

char arr[MAX];

};

// Function to initialize stackvoid init(struct Stack* s) {


s->top = -1;

// Function to push element onto stackvoid push(struct Stack* s, char ch) {

if (s->top < MAX - 1) {

s->arr[++s->top] = ch;

// Function to pop element from stackchar pop(struct Stack* s) {

if (s->top >= 0) {

return s->arr[s->top--];

return '\0';

// Function to reverse a string using stackvoid reverseString(char str[]) {

struct Stack s;

init(&s);

int n = strlen(str);

// Push characters onto stack

for (int i = 0; i < n; i++) {

push(&s, str[i]);

}
// Pop characters to get reversed string

for (int i = 0; i < n; i++) {

str[i] = pop(&s);

int main() {

char str[] = "hello";

printf("Original String: %s\n", str);

reverseString(str);

printf("Reversed String: %s\n", str);

return 0;

Q5a) Quick Sort Algorithm

Quick Sort Algorithm

Quick Sort is a divide-and-conquer sorting algorithm that works as follows:

1. Select a pivot element.


2. Partition the array into two sub-arrays:
1. Left sub-array (elements smaller than the pivot).
2. Right sub-array (elements larger than the pivot).
3. Recursively apply Quick Sort to both sub-arrays.

Sorting the Given Array Using Quick Sort


Initial Array:
[13, 19, 28, 8, 13, 62, 5, 3, 15, 2]

Step-by-Step Sorting Process (Using Pivot = Last Element):

1. Choose pivot = 2, partition:


[2] [13, 19, 28, 8, 13, 62, 5, 3, 15]
2. Choose pivot = 15, partition:
[2, 3, 5, 8, 13, 13] [15] [19, 28, 62]
3. Sort left and right subarrays recursively

[2, 3, 5, 8, 13, 13, 15, 19, 28, 62]

Time Complexity Analysis

 Best Case (O(n log n)) → When pivot divides the array equally.
 Average Case (O(n log n)) → Most cases, balanced partitioning.
 Worst Case (O(n²)) → If the pivot is always the smallest or largest element.

Q5b) Binary Search is an efficient search algorithm for sorted arrays that follows:

1. Find the middle element.


2. If it matches the target, return its index.
3. If the target is smaller, search the left half.
4. If the target is larger, search the right half.
5. Repeat until the element is found or the range is empty.

C Program for Binary Search

#include <stdio.h>

// Binary Search functionint binarySearch(int arr[], int left, int right, int
key) {

while (left <= right) {

int mid = left + (right - left) / 2;

if (arr[mid] == key)

return mid;
if (arr[mid] < key)

left = mid + 1;

else

right = mid - 1;

return -1; // Not found

// Main functionint main() {

int arr[] = {2, 3, 5, 8, 13, 13, 15, 19, 28, 62}; // Sorted array

int n = sizeof(arr) / sizeof(arr[0]);

int key = 15;

int result = binarySearch(arr, 0, n - 1, key);

if (result != -1)

printf("Element %d found at index %d\n", key, result);

else

printf("Element %d not found\n", key);

return 0;

Q6a) Left-Skewed vs. Right-Skewed Binary Trees


 Left-Skewed Tree (Degenerate Left Tree):
o Every node has only a left child, forming a structure similar to a linked list.
o Example:

Right-Skewed Tree (Degenerate Right Tree):

 Every node has only a right child.


 Example

3 \

Constructing an AVL Tree

Given elements in insertion order:


71, 41, 91, 56, 60, 30, 40, 80, 50, 55

Step-by-Step Insertion and Balancing

1. Insert 71 → Root.
2. Insert 41 → Left of 71.
3. Insert 91 → Right of 71.
4. Insert 56 → Right of 41.
5. Insert 60 → Right of 56.
6. Insert 30 → Left of 41.
7. Insert 40 → Right of 30.
8. Insert 80 → Left of 91.
9. Insert 50 → Left of 56 (AVL Rotation needed to balance).
10. Insert 55 → Right of 50 (AVL Rotation needed).

Final AVL Tree After Balancing

56

/ \

41 71

/ \ / \

30 50 60 91

\ \ /

40 55 80

Q6b) Huffman Tree Construction

Given characters and probabilities:

 a = 0.07, b = 0.09, c = 0.12, d = 0.22, e = 0.23, f = 0.27

Step 1: Sort Probabilities in Ascending Order

a(0.07), b(0.09), c(0.12), d(0.22), e(0.23), f(0.27)

Step 2: Construct Huffman Tree

1. Combine a(0.07) + b(0.09) = 0.16


2. Combine c(0.12) + (a+b)(0.16) = 0.28
3. Combine d(0.22) + e(0.23) = 0.45
4. Combine (c,a,b)(0.28) + f(0.27) = 0.55
5. Combine (d,e)(0.45) + (c,a,b,f)(0.55) = 1.00 (Root)

Step 3: Assign Huffman Codes

Character Huffman Code

a 000

b 001

c 01

d 10

e 110

f 111

Step 4: Compute Average Code Length

L=(Pa×La)+(Pb×Lb)+(Pc×Lc)+(Pd×Ld)+(Pe×Le)+(Pf×Lf)L = (P_a \times L_a) +


(P_b \times L_b) + (P_c \times L_c) + (P_d \times L_d) + (P_e \times L_e) +
(P_f \times L_f)L=(Pa×La)+(Pb×Lb)+(Pc×Lc)+(Pd×Ld)+(Pe×Le)+(Pf×Lf)
=(0.07×3)+(0.09×3)+(0.12×2)+(0.22×2)+(0.23×3)+(0.27×3)= (0.07 \times 3)
+ (0.09 \times 3) + (0.12 \times 2) + (0.22 \times 2) + (0.23 \times 3) +
(0.27 \times 3)=(0.07×3)+(0.09×3)+(0.12×2)+(0.22×2)+(0.23×3)+(0.27×3)
=0.21+0.27+0.24+0.44+0.69+0.81= 0.21 + 0.27 + 0.24 + 0.44 + 0.69 +
0.81=0.21+0.27+0.24+0.44+0.69+0.81 =2.66 (Average Code Length)= 2.66
\text{ (Average Code Length)}=2.66 (Average Code Length)

Q7a) Prim’s Algorithm vs. Kruskal’s Algorithm

Feature Prim’s Algorithm Kruskal’s Algorithm

Approach Greedy approach, sorts edges and


Greedy approach, always expands
selects the smallest edge avoiding
Feature Prim’s Algorithm Kruskal’s Algorithm

from the growing MST. cycles.

Start Point Starts from any vertex. Starts with the smallest edge.

Adds the smallest edge that


Edge Adds the smallest edge while
connects an MST node to a non-
Selection ensuring no cycle is formed.
MST node.

Works well for dense graphs Works well for sparse graphs
Graph Type
(many edges). (fewer edges).

Time O(V²) (Adjacency Matrix) or O(E


O(E log E) (Sorting + Union-Find).
Complexity log V) (Min-Heap).

Constructing Minimum Cost Spanning Tree (MST) Using Prim’s Algorithm

Q7b) Dijkstra’s Algorithm for Shortest Path from Vertex 1

We need to find the shortest path from vertex 1 to all other vertices using Dijkstra's
Algorithm.
Step 1: Given Graph Representation

Vertices: {1, 2, 3, 4, 5, 6}

Edges and Weights:

Edge Weight

1 → 29

1 → 34

2 → 4 12

2 → 55

3 → 24

3 → 5 13

4 → 62

5 → 43

5 → 6 15

Step 2: Initialize Distance Table

Vertex Distance from 1 Previous Node

1 0 -

2 ∞ -

3 ∞ -

4 ∞ -

5 ∞ -
Vertex Distance from 1 Previous Node

6 ∞ -

Step 3: Apply Dijkstra’s Algorithm

1.

Start from Vertex 1:

2.
1. Distance to 2 = 9
2. Distance to 3 = 4
3. Updated Table:

Vertex Distance Previous Node

1 0 -

2 9 1

3 4 1

4 ∞ -

5 ∞ -

6 ∞ -

4.
3.

Select the Next Minimum Distance Vertex (3)

4.

1. Distance to 2 via 3 = 4 + 4 = 8 (Less than 9 → Update)


2. Distance to 5 via 3 = 4 + 13 = 17
3. Updated Table:
Vertex Distance Previous Node

1 0 -

2 8 3

3 4 1

4 ∞ -

5 17 3

6 ∞ -

4.
5.

Select the Next Minimum Distance Vertex (2)

6.

1. Distance to 4 via 2 = 8 + 12 = 20
2. Distance to 5 via 2 = 8 + 5 = 13 (Less than 17 → Update)
3. Updated Table:

Vertex Distance Previous Node

1 0 -

2 8 3

3 4 1

4 20 2

5 13 2

6 ∞ -

4.
7.

Select the Next Minimum Distance Vertex (5)

8.

1. Distance to 4 via 5 = 13 + 3 = 16 (Less than 20 → Update)


2. Distance to 6 via 5 = 13 + 15 = 28
3. Updated Table:

Vertex Distance Previous Node

1 0 -

2 8 3

3 4 1

4 16 5

5 13 2

6 28 5

4.
9.

Select the Next Minimum Distance Vertex (4)

10.

1. Distance to 6 via 4 = 16 + 2 = 18 (Less than 28 → Update)


2. Updated Table:

Vertex Distance Previous Node

1 0 -

2 8 3
Vertex Distance Previous Node

3 4 1

4 16 5

5 13 2

6 18 4

3.
11.

Select the Next Minimum Distance Vertex (6)

12.

1. No further updates needed.

Final Shortest Path Distances

Vertex Shortest Distance from 1 Path

1 0 -

2 8 1 → 3 → 2

3 4 1 → 3

4 16 1 → 3 → 2 → 5 → 4

5 13 1 → 3 → 2 → 5

6 18 1 → 3 → 2 → 5 → 4 → 6

Final Answer
1. Shortest paths from vertex 1 to all vertices:

1. Vertex 2: 1 → 3 → 2 (Cost: 8)
2. Vertex 3: 1 → 3 (Cost: 4)
3. Vertex 4: 1 → 3 → 2 → 5 → 4 (Cost: 16)
4. Vertex 5: 1 → 3 → 2 → 5 (Cost: 13)
5. Vertex 6: 1 → 3 → 2 → 5 → 4 → 6 (Cost: 18)

You might also like