0% found this document useful (0 votes)
45 views30 pages

Fds Solved 3

The document explains bubble sort and radix sort algorithms. It provides pseudo code for bubble sort and applies it to sort a sample array. It also explains the radix sort algorithm and applies it to sort another sample array. It discusses the time and space complexity of radix sort.

Uploaded by

subodhdudhmal123
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)
45 views30 pages

Fds Solved 3

The document explains bubble sort and radix sort algorithms. It provides pseudo code for bubble sort and applies it to sort a sample array. It also explains the radix sort algorithm and applies it to sort another sample array. It discusses the time and space complexity of radix sort.

Uploaded by

subodhdudhmal123
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/ 30

Q1) a) Write an algorithm of Bubble sort & sort the following numbers using

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) Write a short note on Fibonacci search with suitable example. [9]


Q3) a) Write pseudo C++ code for addi on of two polynomials using singly
linked list
Ans:-
#include <iostream>
using namespace std;
// Node structure to represent a term in a polynomial
struct Node {
int coefficient;
int exponent;
Node* next;
Node(int coeff, int exp) : coefficient(coeff), exponent(exp), next(nullptr) {}
};
// Func on to add two polynomials represented as linked lists
Node* addPolynomials(Node* poly1, Node* poly2) {
Node* result = nullptr;
Node* tail = nullptr;
while (poly1 != nullptr || poly2 != nullptr) {
int coeff1 = (poly1 != nullptr) ? poly1->coefficient : 0;
int coeff2 = (poly2 != nullptr) ? poly2->coefficient : 0;
int sumCoeff = coeff1 + coeff2;
int exp1 = (poly1 != nullptr) ? poly1->exponent : 0;
int exp2 = (poly2 != nullptr) ? poly2->exponent : 0;
int maxExp = max(exp1, exp2);
Node* newNode = new Node(sumCoeff, maxExp);
if (result == nullptr) {
result = tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
if (poly1 != nullptr) poly1 = poly1->next;
if (poly2 != nullptr) poly2 = poly2->next;
}
return result;
}
// Func on to display a polynomial represented as a linked list
void displayPolynomial(Node* poly) {
while (poly != nullptr) {
cout << poly->coefficient << "x^" << poly->exponent;
poly = poly->next;
if (poly != nullptr) {
cout << " + ";
}
}
cout << endl;
}

// Func on to delete a polynomial represented as a linked list


void deletePolynomial(Node* poly) {
while (poly != nullptr) {
Node* temp = poly;
poly = poly->next;
delete temp;
}
}
int main() {
// Example polynomials: 2x^3 + 4x^2 + 5x^1 + 1 and 3x^2 + 2x^1 + 6
Node* poly1 = new Node(2, 3);
poly1->next = new Node(4, 2);
poly1->next->next = new Node(5, 1);
poly1->next->next->next = new Node(1, 0);
Node* poly2 = new Node(3, 2);
poly2->next = new Node(2, 1);
poly2->next->next = new Node(6, 0);
// Display the original polynomials
cout << "Polynomial 1: ";
displayPolynomial(poly1);
cout << "Polynomial 2: ";
displayPolynomial(poly2);
// Add the polynomials
Node* result = addPolynomials(poly1, poly2);
// Display the result of the addi on
cout << "Sum: ";
displayPolynomial(result);
// Delete the allocated memory
deletePolynomial(poly1);
deletePolynomial(poly2);
deletePolynomial(result);
return 0;
}

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.

b) What are the variants of recursion, explain with example. [9]


Ans:- Recursion is a programming concept where a func on calls itself either directly or
indirectly. There are several variants of recursion, each with its characteris cs. Let's discuss
three common variants of recursion:
1. **Direct Recursion:**
- In direct recursion, a func on calls itself directly.
- Example:
def direct_recursion(n):
if n <= 0:
return
print(n)
direct_recursion(n - 1
direct_recursion(5)
2. **Indirect Recursion:**
- In indirect recursion, two or more func ons call each other in a circular manner.
- Example:
def even(n):
if n == 0:
return True
else:
return odd(n - 1)
def odd(n):
if n == 0:
return False
else:
return even(n - 1)
result = even(5)
print(result)
Output:
True
3. **Tail Recursion:**
- Tail recursion is a special case of direct recursion where the recursive call is the last opera on
in the func on. Some programming languages op mize tail-recursive calls to avoid stack
overflow.
- Example:
def tail_recursion(n, result=1):
if n == 0:
return result
else:
return tail_recursion(n - 1, result * n)
result = tail_recursion(5)
print(result)

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>

// Node class to represent elements in the stack


class Node {
public:
int data;
Node* next;

Node(int value) : data(value), next(nullptr) {}


};

// Stack class using linked implementa on


class LinkedStack {
private:
Node* top;

public:
LinkedStack() : top(nullptr) {}

// Check if the stack is empty


bool is_empty() {
return top == nullptr;
}

// Push an element onto the stack


void push(int value) {
Node* new_node = new Node(value);
new_node->next = top;
top = new_node;
}

// Pop an element from the stack


int pop() {
if (is_empty()) {
std::cerr << "Error: Stack is empty. Cannot pop from an empty stack." << std::endl;
return -1; // Assuming -1 as an error indicator
} else {
int popped_value = top->data;
Node* temp = top;
top = top->next;
delete temp;
return popped_value;
}
}

// Peek at the top element without removing it


int peek() {
if (is_empty()) {
std::cerr << "Error: Stack is empty. Cannot peek an empty stack." << std::endl;
return -1; // Assuming -1 as an error indicator
} else {
return top->data;
}
}

// Display the elements of the stack


void display() {
Node* current = top;
while (current) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
}

// Destructor to deallocate memory


~LinkedStack() {
while (!is_empty()) {
pop();
}
}
};

int main() {
LinkedStack stack;

stack.push(1);
stack.push(2);
stack.push(3);

std::cout << "Stack a er push opera ons:" << std::endl;


stack.display();

std::cout << "Peek: " << stack.peek() << std::endl;

int popped_element = stack.pop();


std::cout << "Popped element: " << popped_element << std::endl;

std::cout << "Stack a er pop opera on:" << std::endl;


stack.display();

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.

Q7) a) Define the following terms with example [8]


i) Linear queue
ii) Circular queue
iii) priority queue
Ans:- **Linear Queue:**
A linear queue is a type of queue where the elements are arranged in a linear or sequen al
order. In a linear queue, elements are added at one end, known as the "rear" or "tail," and
removed from the other end, known as the "front" or "head." The first element that is
enqueued is the first one to be dequeued, following the First-In-First-Out (FIFO) principle.
**Example of Linear Queue:**
A line of passengers wai ng to buy ckets at a reserva on counter. Each new passenger gets in
line a he “rear”; the passenger at the front of the lines is reserved.A linear queue can be found
in a me-sharing computer system where many users share the system simultaneously. The first
element, which is added to the queue will be the first one to be removed. Thus queues are
also called First-in First-Out lists (FIFO) or Last-In-Last-Out lists (LILO).

**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:**

b) Write pseudo C++ code to implement linked queue. [9]


Ans:- #include <iostream>

// Node class to represent elements in the queue


class Node {
public:
int data;
Node* next;

Node(int value) : data(value), next(nullptr) {}


};

// LinkedQueue class represen ng the linked implementa on of a queue


class LinkedQueue {
private:
Node* front; // Front of the queue (head of the linked list)
Node* rear; // Rear of the queue (tail of the linked list)

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;
}

// Enqueue (insert) an element at the rear of the queue


void enqueue(int value) {
Node* new_node = new Node(value);

// 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
}
}

// Dequeue (remove) an element from the front of the queue


int dequeue() {
if (is_empty()) {
std::cerr << "Error: Queue is empty. Cannot dequeue from an empty queue." << std::endl;
return -1; // Assuming -1 as an error indicator
} else {
int dequeued_value = front->data;
Node* temp = front;

// 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
}

delete temp; // Free the memory of the dequeued node


return dequeued_value;
}
}
};

int main() {
LinkedQueue queue;

queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);

std::cout << "Queue a er enqueue opera ons:" << std::endl;


// Display the queue (can be added if needed)

int dequeued_element = queue.dequeue();


std::cout << "Dequeued element: " << dequeued_element << std::endl;

std::cout << "Queue a er dequeue opera on:" << std::endl;


// Display the queue (can be added if needed)

return 0;
}

Q8) a) Explain array implementa on of priority queue with all basic


opera on.[8]
Ans:- In an array implementa on of a priority queue, the elements are stored in an array, and
each element is associated with a priority value. The priority queue maintains the order of
elements based on their priori es, and elements with higher priori es are dequeued before
elements with lower priori es. Below, I'll explain the basic opera ons of an array-based priority
queue:
**Array Implementa on of Priority Queue:**
#include <iostream>
#include <algorithm>
class PriorityQueue {
private:
sta c const int MAX_SIZE = 100; // Maximum size of the priority queue
int elements[MAX_SIZE]; // Array to store elements
int priori es[MAX_SIZE]; // Array to store corresponding priori es
int size; // Current size of the priority queue

public:
PriorityQueue() : size(0) {}

// Check if the priority queue is empty


bool is_empty() {
return size == 0;
}
// Enqueue (insert) an element with a given priority
void enqueue(int element, int priority) {
if (size < MAX_SIZE) {
elements[size] = element;
priori es[size] = priority;
size++;
heapify_up(size - 1);
} else {
std::cerr << "Error: Priority queue is full. Cannot enqueue more elements." << std::endl;
}
}
// Dequeue (remove) the element with the highest priority
int dequeue() {
if (!is_empty()) {
int dequeued_element = elements[0];
elements[0] = elements[size - 1];
priori es[0] = priori es[size - 1];
size--;
heapify_down(0);
return dequeued_element;
} else {
std::cerr << "Error: Priority queue is empty. Cannot dequeue from an empty queue." <<
std::endl;
return -1; // Assuming -1 as an error indicator
}
}
// Display the elements and priori es of the priority queue
void display() {
std::cout << "Priority Queue:" << std::endl;
for (int i = 0; i < size; ++i) {
std::cout << "Element: " << elements[i] << ", Priority: " << priori es[i] << std::endl;
}
}
private:
// Heapify up (used during enqueue to maintain the heap property)
void heapify_up(int index) {
while (index > 0 && priori es[parent(index)] < priori es[index]) {
std::swap(elements[parent(index)], elements[index]);
std::swap(priori es[parent(index)], priori es[index]);
index = parent(index);
}
}
// Heapify down (used during dequeue to maintain the heap property)
void heapify_down(int index) {
int max_index = index;
int le _child = le (index);
int right_child = right(index);
if (le _child < size && priori es[le _child] > priori es[max_index]) {
max_index = le _child;
}

if (right_child < size && priori es[right_child] > priori es[max_index]) {


max_index = right_child;
}

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;
}

// Check if the circular queue is full


bool is_full() {
return (rear + 1) % MAX_SIZE == front;
}
// Enqueue (insert) an element at the rear of the circular queue
void enqueue(int value) {
if (is_full()) {
std::cerr << "Error: Circular queue is full. Cannot enqueue more elements." << std::endl;
} else {
if (is_empty()) {
front = rear = 0;
} else {
rear = (rear + 1) % MAX_SIZE;
}
elements[rear] = value;
}
}
// Dequeue (remove) an element from the front of the circular queue
int dequeue() {
if (is_empty()) {
std::cerr << "Error: Circular queue is empty. Cannot dequeue from an empty queue." <<
std::endl;
return -1; // Assuming -1 as an error indicator
} else {
int dequeued_value = elements[front];
if (front == rear) {
front = rear = -1;
} else {
front = (front + 1) % MAX_SIZE;
}
return dequeued_value;
}
}
// Display the elements of the circular queue
void display() {
if (is_empty()) {
std::cout << "Circular Queue is empty." << std::endl;
} else {
int current = front;
std::cout << "Circular Queue (front -> ";
while (current != rear) {
std::cout << elements[current] << " -> ";
current = (current + 1) % MAX_SIZE;
}
std::cout << elements[current] << " -> rear)" << std::endl;
}
}
};
int main() {
CircularQueue circularQueue;
circularQueue.enqueue(1);
circularQueue.enqueue(2);
circularQueue.enqueue(3);
circularQueue.display();
int dequeued_element = circularQueue.dequeue();
std::cout << "Dequeued Element: " << dequeued_element << std::endl;
circularQueue.display();
return 0;
}

You might also like