Fds Solved 3
Fds Solved 3
Bubble sort & show the contents of an array a er Every pass. [9] 81, 5, 27, –6,
61, 93, 4, 8, 104, 15
Ans:- **Bubble Sort Algorithm:**
Bubble sort is a simple sor ng algorithm that repeatedly steps through the list, compares
adjacent elements, and swaps them if they are in the wrong order. The pass through the list is
repeated un l the list is sorted.
**Algorithm:**
1. Start with the first element (index 0) of the array.
2. Compare the current element with the next element (index 1).
3. If the current element is greater than the next element, swap them.
4. Move to the next pair of elements and repeat steps 2-3 un l the end of the array.
5. A er the first pass, the largest element is guaranteed to be at the end of the array.
6. Repeat steps 1-5 for the remaining unsorted por on of the array (excluding the last element).
7. Con nue this process un l the en re array is sorted
**Pseudo Code:**
procedure bubbleSort(arr: array of integers)
n = length(arr)
for i from 0 to n-1
for j from 0 to n-i-1
if arr[j] > arr[j+1]
swap(arr[j], arr[j+1])
end for
end procedure
**Sor ng the Numbers:**
Let's apply bubble sort to the given array `[81, 5, 27, -6, 61, 93, 4, 8, 104, 15]` and show the
contents of the array a er each pass.
**Pass 1:**
5, 27, -6, 61, 81, 4, 8, 93, 15, 104
**Pass 2:**
5, -6, 27, 61, 4, 8, 81, 15, 93, 104
**Pass 3:**
-6, 5, 27, 4, 8, 61, 15, 81, 93, 104
**Pass 4:**
-6, 5, 4, 8, 27, 15, 61, 81, 93, 104
**Pass 5:**
-6, 4, 5, 8, 15, 27, 61, 81, 93, 104
**Pass 6:**
-6, 4, 5, 8, 15, 27, 61, 81, 93, 104
The array is now sorted, and no more passes are needed. The final sorted array is `[ -6, 4, 5, 8,
15, 27, 61, 81, 93, 104]`.
b) Explain the radix sort . Sort the following numbers in ascending order. [9] 14,
1, 66, 74, 22, 36, 41, 59, 64, 54 Obtain the me & space complexity of your
algorithm.
Ans:- **Radix Sort:**
Radix sort is a non-compara ve sor ng algorithm that works by distribu ng elements into
buckets according to their individual digits. The idea is to process the digits of the numbers from
the least significant digit (LSD) to the most significant digit (MSD) or vice versa. The algorithm
can be applied to numbers in any base (binary, decimal, hexadecimal, etc.).
**Algorithm:**
1. Determine the maximum number of digits among all the numbers.
2. Star ng with the least significant digit (rightmost), sort the numbers based on that digit using
a stable sort (e.g., coun ng sort or bucket sort).
3. Repeat the process for the next significant digit un l the most significant digit is reached.
4. The numbers are now sorted.
**Pseudo Code:**
procedure radixSort(arr: array of integers)
maxDigit = maximum number of digits among all numbers in arr
for i from 1 to maxDigit
// Use a stable sort (e.g., coun ng sort) to sort based on the current digit
coun ngSort(arr, i)
end for
end procedure
**Sor ng the Numbers:**
Let's apply radix sort to the given array `[14, 1, 66, 74, 22, 36, 41, 59, 64, 54]` in ascending order.
1. **First Pass (Least Significant Digit - LSD):**
[ 41, 22, 54, 14, 64, 74, 1, 66, 36, 59 ]
2. **Second Pass:**
[ 1, 14, 22, 36, 41, 54, 59, 64, 66, 74 ]
The array is now sorted. The final sorted array is `[1, 14, 22, 36, 41, 54, 59, 64, 66, 74]`.
**Time Complexity:**
The me complexity of radix sort is O(nk), where n is the number of elements and k is the
number of digits in the maximum number.
**Space Complexity:**
The space complexity is O(n + k), where n is the number of elements and k is the range of the
input (in this case, 10 for digits 0-9). The space is primarily used for the coun ng array in each
pass.
Q2) a) Explain internal & external sor ng by taking suitable example of each
type.
Ans:- Internal Sor ng:
Internal sor ng refers to the sor ng of data en rely held in main memory (RAM). In internal
sor ng, the en re dataset fits into the computer's main memory, allowing for fast access and
manipula on of data. Various sor ng algorithms, such as quicksort, mergesort, heapsort, and
bubble sort, are examples of internal sor ng algorithms.
**Example - Internal Sor ng: Mergesort:**
Mergesort is a divide-and-conquer sor ng algorithm that works well for sor ng large amounts
of data in main memory. It involves recursively dividing the dataset into smaller subproblems,
sor ng each subproblem, and then merging the sorted results.
Suppose we have the following array of integers: `[38, 27, 43, 3, 9, 82, 10]`.
1. **Divide:**
- The array is divided into two halves: `[38, 27, 43]` and `[3, 9, 82, 10]`.
2. **Sort:**
- Each half is recursively sorted using mergesort.
3. **Merge:**
- The two sorted halves are merged to produce the final sorted array: `[3, 9, 10, 27, 38, 43,
82]`.
This process con nues un l the en re dataset is sorted.
**External Sor ng:**
External sor ng is used when the dataset is too large to fit into main memory, and external
storage (e.g., disk or other secondary storage devices) must be u lized. In external sor ng,
por ons of the data are read into memory, sorted internally, and then wri en back to external
storage. This process is repeated un l the en re dataset is sorted.
**Example - External Sor ng: Merge-Sort on Disk:**
Suppose we have a large dataset of records stored in a file on disk, and the dataset is too large
to fit en rely into main memory.
1. **Divide into Runs:**
- The dataset is divided into smaller por ons called runs, each of which can fit into memory.
For example, we divide the file into runs of 100 records each.
2. **Internal Sor ng (Mergesort):**
- Each run is sorted internally using an internal sor ng algorithm like mergesort.
3. **Merge Runs:**
- The sorted runs are then merged into larger runs un l the en re dataset is sorted. This
involves reading por ons of the runs into memory, merging them, and wri ng the merged
results back to disk.
4. **Repeat Merging:**
- The process of merging con nues un l the en re dataset is sorted.
b) What is dynamic data structure? Explain the circular linked list with its basic
opera ons. [9]
Ans:- **Dynamic Data Structure:**
A dynamic data structure is a data structure that can grow or shrink in size during the execu on
of a program. Unlike sta c data structures (e.g., arrays), which have fixed sizes determined at
compile- me, dynamic data structures can allocate and deallocate memory as needed at
run me. This flexibility makes dynamic data structures well-suited for situa ons where the size
of the data is not known in advance or may change dynamically.
Examples of dynamic data structures include linked lists, stacks, queues, trees, and graphs,
where memory is allocated and freed dynamically based on the data structure's requirements.
**Circular Linked List:**
A circular linked list is a type of linked list in which the last node of the list points back to the
first node, crea ng a closed loop. In a circular linked list, each node contains a data element and
a reference (or link) to the next node in the sequence. The last node in the list points to the first
node, forming a circular structure.
**Basic Opera ons on Circular Linked List:**
1.**Inser on:**
- **Insert at the Beginning:** Create a new node, set its next pointer to the current head, and
update the head to the new node.
- **Insert at the End:** Create a new node, set its next pointer to the head, and update the
next pointer of the last node to the new node.
2. **Dele on:**
- **Delete from the Beginning:** Update the head to the next node and free the memory of
the removed node.
- **Delete from the End:** Traverse the list to find the node before the last node, update its
next pointer to the head, and free the memory of the last node.
3. **Traversal:**
- Start from the head and traverse the list by following the next pointers un l reaching the
head again.
4. **Search:**
- Start from the head and traverse the list to find the node with the desired data.
**Pseudo C++ Code for Circular Linked List:**
#include <iostream>
using namespace std;
struct Node {
int data;
struct Node *next;
};
struct Node* head = NULL;
void insert(int newdata) {
struct Node *newnode = (struct Node *)malloc(sizeof(struct
Node));
struct Node *ptr = head;
newnode->data = newdata;
newnode->next = head;
if (head!= NULL) {
while (ptr->next != head)
ptr = ptr->next;
ptr->next = newnode;
} else
newnode->next = newnode;
head = newnode;
}
void display() {
struct Node* ptr;
ptr = head;
do {
cout<<ptr->data <<" ";
ptr = ptr->next;
} while(ptr != head);
}
int main() {
insert(3);
insert(1);
insert(7);
insert(2);
insert(9);
cout<<"The circular linked list is: ";
display();
return 0;
}
Q4) a) Write a pseudo code for the addi on of a node a er the posi on ‘P’ in
singly linked list.
Ans:- Certainly! Below is the pseudo code for adding a node a er the posi on 'P' in a singly
linked list:
Procedure AddNodeA erPosi on(head, data, P)
// Create a new node with the given data
new_node <- Node(data)
// Ini alize a pointer to traverse the list
current <- head
posi on <- 1
// Traverse the list un l the desired posi on or the end is reached
while posi on < P and current is not null do
current <- current.next
posi on <- posi on + 1
end while
// If the posi on is valid, insert the new node a er the current node
if current is not null then
new_node.next <- current.next
current.next <- new_node
else
// If the posi on is invalid, display an error message or take appropriate ac on
Print("Invalid posi on P")
end if
End Procedure
b) Explain the doubly linked list with it’s basic opera ons; list the advantages of
doubly linked list over singly linked list. [9]
Ans:- **Doubly Linked List:**
A doubly linked list is a type of linked list in which each node contains two pointers, one
poin ng to the next node in the sequence (as in a singly linked list) and another poin ng to the
previous node. This bidirec onal linkage allows for traversal in both forward and backward
direc ons. The first node's previous pointer and the last node's next pointer typically point to
NULL.
**Basic Opera ons on Doubly Linked List:**
1. **Inser on:**
- **Insert at the Beginning:** Create a new node, set its next pointer to the current head, set
the current head's previous pointer to the new node, and update the head to the new node.
- **Insert at the End:** Create a new node, set its previous pointer to the last node, set the
last node's next pointer to the new node, and update the last node to the new node.
- **Insert at a Specific Posi on:** Traverse to the desired posi on, adjust the pointers of the
neighboring nodes, and insert the new node.
2. **Dele on:**
- **Delete from the Beginning:** Update the head to the next node, set the new head's
previous pointer to NULL, and free the memory of the removed node.
- **Delete from the End:** Traverse to the last node, update the last node to its previous
node, set the new last node's next pointer to NULL, and free the memory of the removed node.
- **Delete a Specific Node:** Adjust the pointers of the neighboring nodes and free the
memory of the removed node.
3. **Traversal:**
- Start from the head and traverse the list by following the next pointers un l reaching NULL.
4. **Reverse Traversal:**
- Start from the last node and traverse the list by following the previous pointers un l reaching
NULL.
5. **Search:**
- Start from the head (or the tail) and traverse the list to find the node with the desired data.
**Advantages of Doubly Linked List over Singly Linked List:**
1. **Bidirec onal Traversal:**
- Doubly linked lists support traversal in both forward and backward direc ons, which can be
advantageous in certain scenarios.
2. **Ease of Dele on in Some Cases:**
- Dele on of a node in a doubly linked list can be more efficient than in a singly linked list, as it
allows direct access to the previous node.
3. **Inser on and Dele on at Both Ends:**
- Opera ons such as inser on and dele on at the beginning and end of the list are more
efficient in a doubly linked list.
4. **Reverse Traversal:**
- Doubly linked lists allow for easy reverse traversal, which is not possible in a singly linked list
without addi onal data structures.
5. **Inser on and Dele on at a Specific Posi on:**
- Inser on and dele on at a specific posi on can be more efficient in a doubly linked list, as it
allows direct access to both the previous and next nodes.
**Disadvantages:**
- Doubly linked lists require addi onal memory to store the previous pointers, leading to
increased memory overhead.
- Implementa on of doubly linked lists is more complex than singly linked lists due to
bidirec onal pointers.
- Extra care is needed to ensure that the previous pointers are updated correctly during
inser on and dele on opera ons.
Q5) a) Write a pseudo code for basic opera ons of stock. [8]
Ans:- Certainly! Below is a pseudo code for basic opera ons of a stock:
Class Stock
// Member variables
private:
string stockName
int quan ty
double pricePerUnit
// Constructor to ini alize a stock
Stock(string name, int ini alQuan ty, double ini alPrice)
stockName <- name
quan ty <- ini alQuan ty
pricePerUnit <- ini alPrice
// Func on to update the stock quan ty
Func on UpdateQuan ty(newQuan ty)
quan ty <- newQuan ty
// Func on to update the stock price per unit
Func on UpdatePrice(newPrice)
pricePerUnit <- newPrice
// Func on to calculate the total value of the stock
Func on CalculateTotalValue()
totalValue <- quan ty * pricePerUnit
return totalValue
// Func on to display stock informa on
Func on DisplayStock()
Print("Stock Name: ", stockName)
Print("Quan ty: ", quan ty)
Print("Price Per Unit: $", pricePerUnit)
totalValue <- CalculateTotalValue()
Print("Total Value: $", totalValue)
End Class
This pseudo code defines a `Stock` class with basic opera ons. Here's a brief explana on of
each opera on:
- **Constructor (`Stock`):**
- Ini alizes a stock with a given name, ini al quan ty, and ini al price per unit.
- **`UpdateQuan ty` Func on:**
- Updates the quan ty of the stock.
- **`UpdatePrice` Func on:**
- Updates the price per unit of the stock.
- **`CalculateTotalValue` Func on:**
- Calculates the total value of the stock (quan ty * price per unit).
- **`DisplayStock` Func on:**
- Displays informa on about the stock, including its name, quan ty, price per unit, and total
value.
Q6) a) Explain the linked implementa on of stock with suitable example. [8]
Ans:- Procedure for Stack Implementa on Using Linked-List
The linked implementa on of a stack involves using a linked list to represent the elements of
the stack. In this implementa on, each element of the stack is stored in a node, and these
nodes are connected through pointers. The top of the stack is represented by the first node in
the linked list.
#include <iostream>
public:
LinkedStack() : top(nullptr) {}
int main() {
LinkedStack stack;
stack.push(1);
stack.push(2);
stack.push(3);
return 0;
}
b) Write pseudo code for infix to pos ix expression; Explain the need of
conversion of expression.
Ans:- **Pseudo code for Infix to Pos ix Conversion:**
Infix to pos ix conversion involves conver ng an infix expression to its equivalent pos ix form.
The pos ix expression is o en more suitable for evalua on using a stack-based algorithm.
Here's a simple pseudo code for the conversion:
Func on InfixToPos ix(infix_expression):
output_pos ix <- "" // Ini alize an empty string for the pos ix expression
stack <- empty stack // Ini alize an empty stack for operators
For each symbol in infix_expression:
If symbol is operand:
Append symbol to output_pos ix
Else If symbol is '(':
Push symbol onto stack
Else If symbol is ')':
Pop operators from stack and append to output_pos ix un l '(' is encountered
Pop '(' from stack
Else:
// Symbol is an operator
While stack is not empty and precedence of stack top >= precedence of symbol:
Pop operators from stack and append to output_pos ix
Push symbol onto stac
// Pop any remaining operators from stack and append to output_pos ix
While stack is not empty:
Pop operator from stack and append to output_pos ix
Return output_pos ix
End Func on
**Need for Conversion:**
Infix to pos ix conversion is needed for several reasons:
1. **Ease of Evalua on:**
- Pos ix expressions are easier to evaluate using a stack-based algorithm. This simplifies the
process of expression evalua on, especially when dealing with complex expressions involving
mul ple operators and parentheses.
2. **Avoiding Parentheses Ambiguity:**
- Pos ix expressions eliminate the need for parentheses to indicate the order of opera ons.
The posi on of operators in the pos ix expression directly reflects their precedence and
associa vity.
3. **Reducing Complexity:**
- Pos ix expressions can reduce the complexity of expression parsing and evalua on
algorithms, making them more efficient and easier to implement.
4. **Compiler and Interpreter Parsing:**
- In many compilers and interpreters, expressions are converted to pos ix form as an
intermediate step in the parsing process. Pos ix expressions are then used for efficient
evalua on.
Overall, the conversion from infix to pos ix nota on simplifies the process of expression
evalua on and is a crucial step in various applica ons, including compilers, interpreters, and
calculator programs.
**Circular Queue:**
A circular queue is similar to a linear queue, but it has a circular structure. In a circular queue,
when the rear reaches the end of the queue, it wraps around to the front. This avoids the
limita on of a fixed-size linear queue and allows for be er space u liza on.
**Example of Circular Queue:**
Consider a circular queue represented as [Front -> 1, 2, 3, 4, 5 <- Rear]. If 6 is enqueued, the
queue becomes [Front -> 1, 2, 3, 4, 5, 6 <- Rear]. When the rear reaches the end and more
elements are enqueued, it wraps around to the front, crea ng a circular structure.
**Priority Queue:**
A priority queue is a data structure in which each element is assigned a priority, and elements
with higher priority are dequeued before elements with lower priority, regardless of their arrival
order. Priority queues are o en implemented using a variety of data structures, such as heaps
or arrays.
**Example of Priority Queue:**
public:
// Constructor to ini alize an empty queue
LinkedQueue() : front(nullptr), rear(nullptr) {}
// Check if the queue is empty
bool is_empty() {
return front == nullptr;
}
// If the queue is empty, set both front and rear to the new node
if (is_empty()) {
front = rear = new_node;
} else {
rear->next = new_node; // Link the current rear to the new node
rear = new_node; // Update the rear to the new node
}
}
// If the queue has only one element, set both front and rear to nullptr
if (front == rear) {
front = rear = nullptr;
} else {
front = front->next; // Update the front to the next node
}
int main() {
LinkedQueue queue;
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
return 0;
}
public:
PriorityQueue() : size(0) {}
if (index != max_index) {
std::swap(elements[index], elements[max_index]);
std::swap(priori es[index], priori es[max_index]);
heapify_down(max_index);
}
}
// Helper func ons for heap indexing
int parent(int i) {
return (i - 1) / 2;
}
int le (int i) {
return 2 * i + 1;
}
int right(int i) {
return 2 * i + 2;
}
};
int main() {
PriorityQueue priorityQueue;
priorityQueue.enqueue(1, 3);
priorityQueue.enqueue(2, 1);
priorityQueue.enqueue(3, 2);
priorityQueue.display();
int dequeued_element = priorityQueue.dequeue();
std::cout << "Dequeued Element: " << dequeued_element << std::endl;
priorityQueue.display();
return 0;
}
**Explana on of Basic Opera ons:**
1. **Enqueue Opera on:**
- Adds an element to the priority queue with a specified priority.
- The element is added to the end of the array, and then the `heapify_up` opera on is
performed to maintain the heap property.
2. **Dequeue Opera on:**
- Removes the element with the highest priority from the priority queue.
- The element at the root of the heap (index 0) is swapped with the last element in the array,
and then the `heapify_down` opera on is performed to maintain the heap property.
3. **Display Opera on:**
- Displays the elements and their priori es in the priority queue.
4. **Heapify Up Opera on:**
- Used during enqueue to maintain the heap property by moving the newly added element to
the correct posi on in the heap.
5. **Heapify Down Opera on:**
- Used during dequeue to maintain the heap property by adjus ng the posi on of the root
element in the heap.
b) Write a pseudo C++ code to implement Circular queue using array. [9]
Ans:-
pseudo C++ code to implement Circular queue
#include <iostream>
class CircularQueue {
private:
sta c const int MAX_SIZE = 5; // Maximum size of the circular queue
int elements[MAX_SIZE]; // Array to store elements
int front; // Front index of the circular queue
int rear; // Rear index of the circular queue
public:
CircularQueue() : front(-1), rear(-1) {}
// Check if the circular queue is empty
bool is_empty() {
return front == -1 && rear == -1;
}