0% found this document useful (0 votes)
31 views27 pages

FDS SOLVED QB Naaz

The document covers various data structures and algorithms, including representations of arrays (row major and column major), ordered lists, polynomial representation using arrays, and operations on sparse matrices. It also discusses searching techniques such as linear search, sentinel search, binary search, and indexed sequential search, along with their time complexities. Additionally, it explains linked lists and doubly linked lists, including sorting and deletion processes.

Uploaded by

mnaaz052004
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)
31 views27 pages

FDS SOLVED QB Naaz

The document covers various data structures and algorithms, including representations of arrays (row major and column major), ordered lists, polynomial representation using arrays, and operations on sparse matrices. It also discusses searching techniques such as linear search, sentinel search, binary search, and indexed sequential search, along with their time complexities. Additionally, it explains linked lists and doubly linked lists, including sorting and deletion processes.

Uploaded by

mnaaz052004
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

Unit 2

Q1. What is Row Major and Column Major Representation? Explain with an example. Write
the formula to find any element A[i][j] in row major and column major representations of A.

1. Row Major Representation:


If the elements are stored in a row wise manner, then it is called row major representation.
For example, if we want to store elements in row major representation then in a two-dimensional
array

Formula for Address Calculation in Row-Major Order:


Address of A[i][j] = Base Address + [(i×number of columns + j) × size of each element]

2. Column Major Representation:


If elements are stored in column wise manner, then it is called column major representation. For
example, if we want to store elements in column major representation, then in a two-dimensional array:

Q2. Draw and explain following terms:

a.2D Array b. 3D Array


1. Two Dimensional Arrays:
A two-dimensional (2D) array is a collection of elements arranged in rows and columns,
much like a matrix or table. Each element in the array is identified by two indices: one for the
row and one for the column

2. Three Dimensional Arrays:


A three-dimensional (3D) array is an extension of a 2D array that adds another dimension,
often visualized as a collection of 2D arrays stacked on top of each other, forming a cube-like
structure. It is used to store data in a multi-dimensional space.

Q3. Define the term Ordered list?


An ordered list is a collection of elements arranged in a specific sequential order based on a
predefined criterion, such as ascending or descending value, or by the order of insertion.
Example:
A list of numbers sorted in ascending order: [2, 5, 7, 10].
A list of words arranged alphabetically: ["apple", "banana", "cherry"]
Characteristics:
 The elements in an ordered list are arranged based on some logical order (e.g., numerical,
alphabetical).
 Depending on the application, elements may be unique (no duplicates) or can allow repeated
values
 The position of each element is important and defines the order in the list.
 Elements are often accessed by their position (index) in the list.

Q4. Explain with example how single variable polynomial can be represented using 1-D
array? What are advantage and disadvantage of this representation?
Representation using arrays:
Polynomial is the sum of terms where each term consists of variable, coefficient and exponent. For
representing a single variable polynomial one can make use of one-dimensional array. In single
dimensional array the index of an array will act as the exponent and the coefficient can be stored at that
particular index which can be represented as follows:
For example, 3x4 + 5x3 + 7x2 + 10x – 19
This polynomial can be stored in single dimensional array.
Advantages and Disadvantages of Representing Single Variable Polynomial Using 1D Array

Advantages Disadvantages
Easy to implement and manage due to its Wastes space for coefficients with zero values.
simplicity
Accessing coefficients using index is efficient Limited to polynomials of fixed degree
Useful for storing dense polynomials Insertion or deletion of terms is not flexible

Q5. Write an algorithm to add two sorted polynomials in single variable. Analyze its time
complexity?
Algorithm:
Step1:
Initialize three pointers: i for P1[ ], j for P2[ ], and k for the Result[ ] array.
Step2:
Compare the exponents of the current terms from P1[ ] and P2[ ]:
 If the exponent in P1[ ] is greater, add the term to Result[ ] and increment i.
 If the exponent in P2[ ] is greater, add the term to Result[ ] and increment j.
 If the exponents are equal, add the coefficients. If the sum is not zero, add the resulting term to
Result[ ], and increment both i and j.
Step3:
Append any remaining terms from P1[ ] or P2[ ] to Result[ ].
Step4:
Return Result[ ].

Time Complexity Analysis:


1. Traversal: Each term in P1 and P2 is processed exactly once.
2. Comparisons and Insertions: Constant time for each comparison and insertion.
Total time complexity:
𝑂(𝑛+𝑚)
where 𝑛 and 𝑚 are the number of terms in P1 and P2, respectively.

[Link] pseudo C/C++ code to perform polynomial multiplication using array?

Step 1: Start.
Step 2: Input the two polynomials P1[] and P2[], each containing pairs
of coefficients and exponents.
Step 3: Initialize an empty array result[] to store the result of the
multiplication.
Step 4: For each term in P1[] (with index i):
Step 4.1: For each term in P2[] (with index j):
Step 4.1.1: Multiply the coefficients:
coeff = P1[i].coefficient * P2[j].coefficient.
Step 4.1.2: Add the exponents:
expo = P1[i].exponent + P2[j].exponent.
Step 4.1.3: Check if a term with the same exponent already
exists in result[]:
 If yes, add the new coefficient to the existing term.
 If no, add a new term {coeff, expo} to result[].
Step 5: Combine like terms (if necessary).
Step 6: Output the result array result[].
Step 7: Stop.

Time Complexity:
 The outer loop iterates over all terms in the first polynomial P1[], and the inner loop
iterates over all terms in the second polynomial P2[].
 Time Complexity: O(n × m), where:
 n is the number of terms in P1[],
 m is the number of terms in P2[].

Q7. What is meant by sparse Matrix? Write an algorithm to perform addition of two sparse
matrices. And analyze its time complexity
A sparse matrix is a matrix that has a majority of its elements as zeroes. In other words, only a few
elements in the matrix are non-zero, and the rest are zero.
For example, if the matrix is of size 100 x 100 and only 10 elements are non-zero. Then for accessing
these 10 elements one has to make 10000 times scan. Also, only 10 spaces will be with non-zero
elements. The remaining spaces of matrix will be filled with zeros only. i.e. we have to allocate the
memory of 100 x 100 x 2 = 20000

Algorithm for sparse matrix addition:

Step1: obtain the triplet form of both sparse matrices.


Step2: create new triplet to store result as result matrix.
Step3: copy number of rows and column from any sparse matrix to result matrix.
Step4: let I, j, k be the indices of sparse matrices 1, 2, 3 respectively.
Step5: initialize I, j, k to 1.
Step6: traverse both matrices from second row.
If (row-value of matrix 1 = = row-value of matrix 2)
{
If (column-value of matrix 1 = = column-value of matrix 2)
Make the addition of non-zero values and store it into result matrix by incrementing all
indices.
Else
Whichever has less column values copy that to result matrix by incrementing respective
indices.
}
Else
Compare rows of both sparse matrices and whichever has less row-value copy that to result
matrix by incrementing respective indices.
Step7: repeat step 6 till the end of any sparse matrix’s triplet.
Step8: copy the remaining term of sparse matrix (if any) to the resulting matrix.

Time Complexity Analysis:


1. Comparison and Addition: Each non-zero element of A and B is processed exactly once.
𝑂(𝑛+𝑚), where 𝑛 and 𝑚 are the number of non-zero elements in A and B.
2. Appending Remaining Elements: In the worst case, all remaining elements are appended, still
𝑂(𝑛+𝑚)
Total Time Complexity:
𝑂(𝑛+𝑚)

Q8. Write an algorithm for multiplication of sparse matrix. comment on time and space
complexity for both.
Steps:
Step1: Validate Dimensions:
Ensure that the number of columns in matrix A equals the number of rows in matrix B. If not,
return an error.

Step2: Transpose Matrix B:


Transpose B[] to make column access efficient during multiplication.

Step3: Initialize Result Array:


Create an empty Result[] array to store non-zero elements of the product.
Step4: Multiply Row by Column:
 For each row in A, iterate through its non-zero elements.
 For each element, find matching elements in B (from the transposed matrix) where column
indices match row indices of the current term in A.
 Compute the product of their values, sum up for the same position in the resultant matrix, and
store the result.
Step5: Combine Terms:
If multiple products result in the same position, combine their values.
Step6:
Return Result: Return Result[ ] containing non-zero elements.

Time Complexity:
 Transpose 𝐵: 𝑂(𝑙)
 Matrix Multiplication: 𝑂(𝑘⋅𝑙), where 𝑘 and 𝑙 are the non-zero elements in 𝐴 and 𝐵
 Result Combination: 𝑂(𝑘.𝑙) in the worst case.
Overall Time Complexity: 𝑂(𝑘⋅𝑙)
Space Complexity:
 Transpose of 𝐵: 𝑂(𝑙)
 Intermediate Results: 𝑂(𝑘 ⋅𝑙)
Overall Space Complexity: 𝑂(𝑘⋅𝑙)

Q9. What is the difference between simple and fast transpose of sparse matrix? Write an
algorithm to find simple transpose of sparse matrix.

Simple transpose Fast transpose


Uses nested loops to directly interchange rows and Uses auxiliary arrays to compute the result in
columns. fewer steps.
Inefficient for larger matrices due to multiple Efficient as it minimizes operations by
iterations over non-zero elements. precomputing positions of elements.
Time complexity is O(n×t), where 𝑛 is the number Time complexity is O(t+n) where 𝑡 is the number
of rows and 𝑡 is the number of non-zero terms. of non-zero terms and 𝑛 is the number of columns.
Does not require extra memory apart from the Requires extra memory for auxiliary arrays like
result matrix. position and count arrays.
Suitable for small matrices or when efficiency is Preferred for large sparse matrices where speed is
not a priority. essential.
Algorithm for simple transpose of matrix:
Step 1: Start
Step 2: Input sparse matrix A[] in triplet form (with m rows, n columns, and k non-zero elements).
Step 3: Initialize an empty result matrix T[] for the transpose.
Step 4: For each element A[i] in A (where i ranges from 1 to n):
Step 4.1: Swap A[i].row with A[i].column.
Step 4.2: Insert the transposed element into result matrix T[].
Step 5: Sort the matrix T[] by row (now the original columns) and by column (now the original rows).
Step 6: Output the transposed matrix T[].
Step 7: Stop
Q10. Explain sequential memory organization using suitable data structure?
Sequential memory organization refers to storing data elements in a continuous block of memory, where
elements are placed one after another in sequence. This organization is commonly used in arrays as the
underlying data structure.
Advantages:
Fast random access.
Simple implementation and traversal.
Disadvantages:
Fixed size may lead to wasted memory or insufficient storage.
Costly insertion and deletion for non-terminal positions.

Example:
Unit 3

Q3 Explain in brief the different searching techniques. What is the time complexity of each of them?

1. Linear search:
Linear search is a method for searching for an element in a collection of elements. In linear search, each
element of the collection is visited one by one in a sequential fashion to find the desired element.
Time Complexity:
Best Case: 𝑂(1)
(if the target is at the first position).
Worst Case: 𝑂(𝑛)
(if the target is not found or at the last position).

2. Sentinel Search:
A variant of Linear Search where a "sentinel" (extra element) is added to the end of the array to
eliminate boundary checks during the search.
Time Complexity:
Best Case: 𝑂(1)
Worst Case: 𝑂(𝑛)

3. Binary search:
Binary search is an algorithm for sorted data, uses divide-and-conquer strategy for sorting. It compares
the middle element with the target: if they match, the index is returned; if the target is smaller, it
searches the left subarray; otherwise, the right. This continues until the target is found or the array size
becomes zero.
Time Complexity:
Best Case: 𝑂(1)
Worst Case: 𝑂(log𝑛)

4. Fibonacci Search:
Uses Fibonacci numbers to divide the array into sections for searching, similar to Binary Search but
with different partitioning logic.
Time Complexity:
Best Case: 𝑂(1)
Worst Case: 𝑂(log𝑛)

5. Indexed sequential search:


Indexed Sequential Search is a search algorithm that combines sequential search with indexing to make
searching faster in large datasets.
Time Complexity:
Best Case: 𝑂(1)
Worst Case: 𝑂(𝑛)
(depends on block size).
Q7. Write a short note on sentinel search & Index sequential search with suitable example.

Sentinel search:
Sentinel Search is a variation of the linear search algorithm that slightly optimizes
performance by reducing the number of comparisons in the search loop. It does this by placing
a special "sentinel" element at the end of the array, which guarantees that the search will always
terminate without needing to check for the end of the list inside the loop.
Working of Sentinel Search:
A sentinel is placed at the end of the list, which is usually the element you're searching
for.
The algorithm searches for the target by moving sequentially through the list.
Because of the sentinel, the search loop doesn't need to check if the end of the list is
reached—it will always find the sentinel, allowing it to stop without extra checks.
After finding the sentinel, the algorithm checks if the actual target was found in the
original list (and not just the sentinel).

Example of Sentinel Search


Indexed Sequential Search:
Indexed Sequential Search is a search algorithm that combines sequential search with
indexing to make searching faster in large datasets. It is especially useful when the data is too
large to be efficiently searched using just sequential search but doesn't require the complexity
of more advanced algorithms like binary search.
Unit 4

Q1. What is linked list? Write a pseudo-C++ code to sort the elements.

A linked list is a linear data structure which can store a collection of "nodes" connected together via
links i.e. pointers. Linked lists nodes are not stored at a contiguous location, rather they are linked using
pointers to the different memory locations. A node consists of the data value and a pointer to the address
of the next node within the linked list.
A linked list is a dynamic linear data structure whose memory size can be allocated or de-allocated at run
time based on the operation insertion or deletion, this helps in using system memory efficiently. Linked
lists can be used to implement various data structures like a stack, queue, graph, hash maps, etc.

Pseudo code to sort the elements:

FUNCTION SortLinkedList(head)
IF head IS NULL
RETURN // List is empty

DO
swapped = FALSE
current = head

WHILE [Link] IS NOT NULL


IF [Link] > [Link] THEN
SWAP [Link], [Link]
swapped = TRUE

current = [Link]

WHILE swapped IS TRUE

Q2. What is doubly linked list? Explain the process of deletion of an element fromdoubly linked
list with example.

A doubly linked list is a data structure that consists of a set of nodes, each of which contains a value
and two pointers, one pointing to the previous node in the list and one pointing to the next node in the
list. This allows for efficient traversal of the list in both directions, making it suitable for applications
where frequent insertions and deletions are required.

Deletion in a Doubly Linked List


Deletion in a doubly linked list involves removing a specified node and updating the pointers of the
adjacent nodes to maintain the integrity of the list. The deletion can occur at the beginning, end, or at a
specific position.
To delete an element:

1. Locate the node to be deleted.


2. Update the next* pointer of the previous node to point to the next node of the node being deleted.
3. Update the prev* pointer of the next node to point to the previous node of the node being deleted.
4. Free the memory of the node being deleted.

Steps for Deletion:


Delete from the beginning:
 Update head to point to the second node.
 Set the prev pointer of the new head to NULL.
 Delete the original head node.

Delete from the end:


 Update the next pointer of the second last node to NULL.
 Delete the last node.

Delete a specific node:


 Locate the node to delete.
 Update the next pointer of the previous node and the prev pointer of the next node to bypass the
node being deleted.

Example:

Initial list:
1 2 3 4

delete the node with value 3.


1. Locate the node containing value 3.
2. Update:
[Link] to point 4.
[Link] to point 2.
3. Free the memory of the node containing 3.
Resulting list:

1 2 4
Q3. Write a pseudo code to insert new node in to singly link list
1. Pseudo code to insert at beginning:
FUNCTION InsertAtBeginning(head, value)
CREATE newNode
[Link] = value
[Link] = head
head = newNode
RETURN head

2. Pseudo code to insert at end:


FUNCTION InsertAtEnd(head, value)
CREATE newNode
[Link] = value
[Link] = NULL

IF head IS NULL
head = newNode
RETURN head

current = head
WHILE [Link] IS NOT NULL
current = [Link]
END WHILE

[Link] = newNode
RETURN head

3. Pseudo code to insert at any position:


FUNCTION InsertAtPosition(head, value, position)
CREATE newNode
[Link] = value

IF position = 1
[Link] = head
head = newNode
RETURN head
current = head
count = 1

WHILE current IS NOT NULL AND count < position - 1


current = [Link]
count = count + 1
END WHILE

IF current IS NULL
PRINT "Position out of range"
RETURN head

[Link] = [Link]
[Link] = newNode
RETURN head

Q4. What is dynamic data structure. Explain with circular linked list with its basic operations.

Dynamic Data Structure


A dynamic data structure is a structure that can grow or shrink in size during runtime, depending on the
program's requirements. Unlike static data structures like arrays, dynamic data structures do not require
a fixed size to be defined at compile time. Memory is allocated and deallocated dynamically, making
them memory-efficient.

Circular Linked List


A circular linked list is a variation of a linked list where:
 The last node points back to the first node, forming a circle.
 It can be singly or doubly circular.

In a singly circular linked list, each node has:


 data: The value stored in the node.
 next: Pointer to the next node (last node points to the first node).

Basic Operations on Circular Linked List


1. Insertion
At the Beginning:
1. Create a new node.
2. Set the next of the new node to the head.
3. Update the last node's next to the new node.
4. Update the head to the new node.

At the End:
1. Create a new node.
2. Traverse the list to the last node.
3. Set the next of the last node to the new node.
4. Set the next of the new node to the head.
[Link]
From the Beginning:
1. Update the head to the next node.
2. Update the last node's next to the new head.
3. Free the old head.

From the End:


1. Traverse the list to the second last node.
2. Update its next to the head.
3. Free the last node.

[Link]
Start from the head and move through the list, printing the data of each node until reaching the head
again.

Q5. Write and explain node structure of Circular Singly Linked List and DoublyLinked list.
Write pseudocode for concatenation of two doubly linked lists.

Circular linked list:


A node in a circular linked list has the following components:
1. Data: Stores the value of the node.
2. Next Pointer: Points to the next node in the list.

 In a circular linked list, the next pointer of the last node points back to the first node, forming a
circle.

Node Structure of circular linked list:

struct Node {
int data; // Value stored in the node
Node* next; // Pointer to the next node
};

Doubly Linked List:


A node in a doubly linked list has the following components:
1. Data: Stores the value of the node.
2. Prev Pointer: Points to the previous node in the list.
3. Next Pointer: Points to the next node in the list.

Node Structure of doubly linked list:

struct Node {
int data; // Value stored in the node
Node* prev; // Pointer to the previous node
Node* next; // Pointer to the next node
};
Pseudo code steps for concatenation of two doubly linked list:
Steps(just for reference)
1. If list1 is empty, return list2 as the concatenated list.
2. If list2 is empty, return list1 as the concatenated list.
3. Traverse list1 to its last node.
4. Link the next pointer of the last node of list1 to the head of list2.
5. Link the prev pointer of the head node of list2 to the last node of list1.
6. Return the updated list1 as the concatenated list.

Pseudo code:

FUNCTION Concatenate(list1, list2)


// If list1 is empty, return list2
IF list1 IS NULL
RETURN list2

// If list2 is empty, return list1


IF list2 IS NULL
RETURN list1

// Traverse to the last node of list1


current = list1
WHILE [Link] IS NOT NULL
current = [Link]
END WHILE

// Link the last node of list1 to the head of list2


[Link] = list2
[Link] = current

// Return the concatenated list


RETURN list1
END FUNCTION
Q6. Explain Generalized Linked List with example.

A generalized linked list (GLL) is an extension of a regular linked list where each node can store either
an atomic data element (such as an integer, character, etc.) or a pointer to another generalized linked
list. This structure allows representation of hierarchical or nested data.

 Flag = 0 means variable is present


 Flag = 1 means down pointer is present
 Flag = 2 means coefficient and exponent is present

Example:

9x5 + 7x4 y + 10xz

The head node contains variable x and pointer to next node.


Temp contains flag 2 means it represents coefficient and exponent of variable x.
This entirely indicates 9x5.

Now temp1 node contains flag 1 which indicates it has another variable and it points down.
Temp2 node contains flag 0 which indicates it has a variable y and points right to next node temp3,
which contains flag 2 which represents coefficient and exponent of variable xy.
This entirely indicates 7x4y.

Now temp4 node contains flag1 which indicates a new variable z and down pointer.
temp5 contains flag 0 which indicates variable z and a next pointer.
Temp6 contains flag 2 which represents coefficients and exponent of variable xz.
and this entirely indicates 10xz.

Q7. Explain the representation of polynomial using GLL.


Polynomials can be effectively represented using generalized linked lists (GLL). In this representation,
each node stores a term of the polynomial, which consists of:

1. Coefficient (numeric value).


2. Exponent (power of the variable).
3. Pointer to the next term.
In cases where a polynomial has multiple variables (e.g., x3 + 2x2 y + y2)
the exponents of each variable can be stored as a sub-list.
(refer previous question’s example)

Q8. Write and explain use of Generalized linked list for representation of multivariable polynomial with
suitable example. Explain node structure.
Generalized Linked List (GLL) is an effective way to represent multivariable polynomials, as it allows
hierarchical storage of terms and their associated variables with exponents.
Use of GLL for Multivariable Polynomials:
 Dynamic Structure: GLL can handle polynomials with any number of variables and terms
dynamically.
 Hierarchy: The main list stores terms, and each term can have a sublist to store variable-exponent
pairs.
 Efficiency in Representation: Unlike arrays, GLL avoids fixed memory allocation and is more
space-efficient for sparse polynomials.
 Flexibility: Easily represents polynomials with varying numbers of variables and degrees.
(same example)

Node structure:
// Node for exponents of variables
struct ExpNode {
char variable; // Name of the variable (e.g., x, y)
int exponent; // Power of the variable
ExpNode* next; // Pointer to the next variable in the sublist
};

// Node for polynomial terms


struct PolyNode {
int coefficient; // Coefficient of the term
ExpNode* exponents; // Pointer to sublist for variable exponents
PolyNode* next; // Pointer to the next term in the polynomial
};
Unit 5

Q1. Write a pseudo code for basic operation of stack.


Pseudo code for basic operations of stack:
Stack:
Initialize stack as empty list or array

Push(stack, element):
Add element to the top of the stack
[Link](element)

Pop(stack):
If stack is not empty:
element = [Link]()
Return element
Else:
Return "Stack is empty"

Peek(stack):
If stack is not empty:
Return the top element of the stack
Else:
Return "Stack is empty"

IsEmpty(stack):
If stack is empty:
Return True
Else:
Return False

Size(stack):
Return the number of elements in the stack
Q2. Write pseudo-C/C++ code to implement stack using Singly linked list withoverflow and underflow
conditions.

Node:
data // Holds the value of the node
next // Pointer to the next node

Stack:
top // Points to the top node of the stack
maxSize // Maximum size of the stack (for overflow check)

InitializeStack(maxSize):
top = NULL
maxSize = maxSize

Push(stack, element):
If stack is full (size >= maxSize):
Print "Stack Overflow"
Return
Create newNode with data = element
[Link] = [Link]
[Link] = newNode

Pop(stack):
If stack is empty (top == NULL):
Print "Stack Underflow"
Return
temp = [Link]
[Link] = [Link]
Print "Popped element: " + [Link]
Return [Link]

Peek(stack):
If stack is empty (top == NULL):
Print "Stack is empty"
Return
Return [Link]

IsEmpty(stack):
If [Link] == NULL:
Return True
Else:
Return False

Size(stack):
count = 0
current = [Link]
While current is not NULL:
count = count + 1
current = [Link]
Return count
Q3. Write rules to convert given infix expression to postfix expression using stack. Convert expression
(P * Q – (L + M * N) ^ (X * Y / Z) stepwise using the above rules. Where ^ is - exponential operator

Rules to Convert Infix to Postfix Using a Stack:

1. Operands:
 Directly add operands (e.g., variables or numbers) to the postfix expression.

2. Operators:
 If the stack is empty, push the operator onto the stack.
 If the stack is not empty, compare the precedence of the operator with the operator on top of
the stack:
• If the current operator has higher precedence: Push it onto the stack.
• If the current operator has lower or equal precedence: Pop operators from the
stack and add them to the postfix expression until the stack is empty or a lower-
precedence operator is found. Then, push the current operator onto the stack.

3. Parentheses:
 Left Parenthesis (: Push it onto the stack.
 Right Parenthesis ): Pop and add operators from the stack to the postfix expression until a left
parenthesis ( is found. Then, pop and discard the (.

4. End of Expression:
 After processing the entire infix expression, pop any remaining operators from the stack and
add them to the postfix expression.

Expression: (P * Q – (L + M * N) ^ (X * Y / Z) )

symbol Stack Postfix expression


( (
P ( P
* (* P
Q (* PQ
- (- PQ*
( (-( PQ*
L (-( PQ*L
+ (-(+ PQ*L
M (-(+ PQ*LM
* (-(+* PQ*LM
N (-(+* PQ*LMN
) (- PQ*LMN*+
^ (-^ PQ*LMN*+
( (-^( PQ*LMN*+
X (-^( PQ*LMN*+X
* (-^(* PQ*LMN*+X
Y (-^(* PQ*LMN*+XY
/ (-^(/ PQ*LMN*+XY*
Z (-^(/ PQ*LMN*+XY*Z
) (-^ PQ*LMN*+XY*Z/
) PQ*LMN*+XY*Z/^-
Q4. . What is the need to convert the infix expression into postfix;
convert the following expression into postfix expression (a+b) * d + e/(f + a*d) + c.

The main need to convert an infix expression into postfix is to simplify the process of evaluating
expressions, particularly in computer systems and compilers.
Here’s why postfix (or Reverse Polish Notation, RPN) is useful:
1. No Parentheses: Postfix removes the need for parentheses by handling operator precedence
automatically.
2. Easy Evaluation: Postfix is processed sequentially using a stack, making it simpler for machines.
3. Efficient for Compilers: Compilers use postfix for intermediate code generation and faster
computation.
4. Stack-Based Compatibility: It aligns with stack-based architectures, ensuring smooth evaluation.

Expression: (a+b) * d + e/(f + a*d) + c

symbol Stack Postfix expression


( (
a ( a
+ (+ a
b (+ ab
) ab+
* * ab+
d * ab+d
+ + ab+d*
e + ab+d*e
/ +/ ab+d*e
( +/ ab+d*e
f +/( ab+d*ef
+ +/(+ ab+d*ef
a +/(+ ab+d*efa
* +/(+* ab+d*efa
d +/(+* ab+d*efad
) +/ ab+d*efad*+
+ + ab+d*efad*+/+
c + ab+d*efad*+/+c
ab+d*efad*+/+c+

Q5. Explain procedure to convert infix expression to prefix expression and postfix
evaluation with example.

Steps to convert infix expression to prefix expression:

1. Reverse the Infix Expression:


 Reverse the expression.
 Swap ( with ) and vice versa.

2. Apply Infix-to-Postfix Rules:


 Use a stack to handle operators and parentheses while scanning the reversed
expression.
 Push operators onto the stack, and add operands directly to the prefix result.
3. Reverse the Result:
 Reverse the postfix-like result obtained to get the prefix expression.

Example:
Steps to Evaluate Postfix Expression:

1. Initialize an Empty Stack:


Use the stack to store operands during evaluation.

2. Scan the Expression:


Read the postfix expression from left to right.

3. Process Each Symbol:


 If Operand: Push it onto the stack.
 If Operator:
• Pop the top two operands from the stack.
• Apply the operator to these operands.
• Push the result back onto the stack.

4. Repeat Until End:


Continue the above steps for all symbols in the expression.

5. Result:
At the end of the evaluation, the stack will contain a single value, which is the
result of the postfix expression.

Example:
Q6. Write algorithm for postfix expression evaluation. Explain with suitable example.

Algorithm:

1. Initialize an Empty Stack:


 Create a stack to store operands during evaluation.

2. Scan the Expression:


 Read the postfix expression from left to right.

3. Process Each Symbol:


 If the symbol is an operand:
• Push it onto the stack.
 If the symbol is an operator:
• Pop the top two operands from the stack.
• Apply the operator to these operands in the correct order:
 For +, -, *, /:
• Let op1 be the second operand popped and op2 be the first.
• Compute op1 operator op2.
 Push the result back onto the stack.

4. Repeat Until the End:


 Continue steps 2 and 3 for all symbols in the expression.

5. Final Result:
 At the end, the stack will contain a single value, which is the result of the postfix expression.

(previous question’s example for this)

Q7. What is the concept of recursion? Explain the use of stack in recursion with example.

Recursion is a programming technique in which a function calls itself to solve a problem. The function
typically divides the problem into smaller subproblems, solving each recursively until a base condition
(termination condition) is met. At that point, the function begins returning results back to the previous
calls, effectively "unwinding" the recursion.

Use of Stack in Recursion:


In recursion, the function calls are stored in a call stack. Each time a function calls itself, a new frame
is pushed onto the stack with the parameters and the return address. When the base case is reached, the
stack starts unwinding, and each function call returns its result.
Example:
Factorial(n):
If n == 0:
Return 1
Else:
Return n * Factorial(n - 1)

Working:
Factorial(5) → 5 * Factorial(4)
Factorial(4) → 4 * Factorial(3)
Factorial(3) → 3 * Factorial(2)
Factorial(2) → 2 * Factorial(1)
Factorial(1) → 1 * Factorial(0)
Factorial(0) → 1 (base case)
Q8. What are the variants of recursion. Explain with example
1. Direct Recursion
A function directly calls itself to solve a smaller instance of the problem.
Example: Factorial function
Factorial(n):
If n == 0:
Return 1
Else:
Return n * Factorial(n - 1)

2. Indirect Recursion
A function calls another function, which in turn calls the original function.
Example:

Function A():
Call Function B()

Function B():
Call Function A()

3. Tail Recursion
The recursive call is the last operation performed in the function, with no additional work after it.
Optimized by compilers into iterative solutions.
Example:
TailRec(n, result):
If n == 0:
Return result
Else:
Return TailRec(n - 1, result * n)

4. Head Recursion
The recursive call is the first operation performed in the function, and any processing occurs after the
recursive call.
Example:
HeadRec(n):
If n > 0:
HeadRec(n - 1)
Print n

5. Tree Recursion
A function makes multiple recursive calls to itself, resulting in a tree-like structure of calls.
Example: Fibonacci sequence
Fibonacci(n):
If n <= 1:
Return n
Else:
Return Fibonacci(n - 1) + Fibonacci(n - 2)
Q9. What is backtracking algorithm design strategy? How stack is useful in backtracking?

Backtracking is a problem-solving strategy that builds a solution incrementally by exploring all


potential options and discarding solutions that do not satisfy the problem’s constraints. It is
commonly used for problems involving permutations, combinations, or searching in structures data
like graphs or trees.
Steps in backtracking:

1. Recursively exploration: Solve the problem step by step recursively.

2. Base case: define the conditions when a solution is complete.

3. Constraints checking: abandon a solution if it violates constraints.

4. Backtrack: undo the last step (partial solution) and try another path.

Use of stack in backtracking:


A stack is used in backtracking to keep track of choices made while solving a problem. It helps the
algorithm explore all possible solutions by:

1. Remembering Decisions: Each step or choice is stored in the stack so you can revisit it if
needed.

2. Undoing Mistakes: If a decision doesn't work (violates constraints or leads to a dead end),
the stack "pops" the last choice, allowing the algorithm to backtrack and try another path.

3. Exploring All Paths: The stack helps the algorithm systematically explore all possible solutions
by revisiting earlier decisions.

You might also like