Dsbig 5
Dsbig 5
Example:
Example:
Example:
Example:
Example:
Step Count:
Pseudocode:
c
for (i = 0; i < m; i++) { // m iterations
for (j = 0; j < p; j++) { // p iterations
C[i][j] = 0;
for (k = 0; k < n; k++) { // n iterations
C[i][j] += A[i][k] * B[k][j]; // 1 multiplication + 1 addition
}
}
}
Total Steps:
Example:
Multiply A[2×3] and B[3×2]:
Multiplications: 2 × 3 × 2 = 12.
Key Points:
Standard Time Complexity: O(n³) for square matrices (m = n = p).
Key Takeaways
Algorithmic Notations:
Matrix Multiplication:
Example:
Text: "ABABDABACDABABCABAB"
For each position i in the text, check if the pattern matches starting at i.
If a mismatch occurs, shift the pattern by 1 position.
Pseudocode:
c
void naiveSearch(char *text, char *pattern) {
int n = strlen(text);
int m = strlen(pattern);
for (int i = 0; i <= n - m; i++) {
int j;
for (j = 0; j < m; j++) {
if (text[i + j] != pattern[j])
break;
}
if (j == m) {
printf("Pattern found at index %d\n", i);
}
}
}
Time Complexity:
int main() {
char text[100], pattern[100];
printf("Enter the main string: ");
fgets(text, sizeof(text), stdin);
text[strcspn(text, "\n")] = ’\0’; // Remove newline
findSubstring(text, pattern);
return 0;
}
Explanation:
Input Handling:
Substring Search:
Example:
Input:
Substring: "llo"
Key Takeaways
Naive Algorithm:
C Program:
Efficient Deletions:
Flexible Insertions:
Disadvantages:
Higher Memory Usage:
Stores two pointers (next + prev) per node → 33% more memory than singly linked lists.
Complex Implementation:
More pointer manipulations (e.g., updating prev and next during insertions/deletions).
Slower Operations:
Extra pointer updates slightly slow down insert/delete compared to singly linked lists.
Key Trade-off:
Use Case: Choose doubly linked lists when backward traversal is needed (e.g., undo/redo features).
Key Takeaways
Singly Linked List:
If head->data == item, update head = head->next and free the old head.
If current->data == item:
Free current.
Exit.
Pseudocode:
c
void deleteNode(struct Node **head, int item) {
if (*head == NULL) {
printf("List is empty.\n");
return;
}
struct Node *current = *head;
struct Node *prev = NULL;
// Traverse list
while (current != NULL && current->data != item) {
prev = current;
current = current->next;
}
// Case 2: Item not found
if (current == NULL) {
printf("Item not found.\n");
return;
}
Operands → Output.
Pseudocode:
c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
char stack[MAX];
int top = -1;
int main() {
char infix[MAX] = "(A+B)*C-D";
char prefix[MAX];
infixToPrefix(infix, prefix);
printf("Prefix: %s\n", prefix); // Output: "-*+ABCD"
return 0;
}
Example:
Infix: (A + B) * C - D
Reversed: D - C ) B + A (
Postfix: D C B A + * -
Prefix: - * + A B C D
Infix to Prefix:
21(a) Algorithm for Insert (Enqueue) and Delete (Dequeue) Operations on a Queue (5 Marks)
Queue Properties:
FIFO (First-In-First-Out) structure.
Operations:
If the queue is empty, set both front and rear to the new node.
Else, link rear->next to the new node and update rear = newNode.
struct Node {
int data;
struct Node *next;
};
void dequeue() {
if (front == NULL) {
printf("Queue is empty.\n");
return;
}
struct Node *temp = front;
front = front->next;
if (front == NULL) {
rear = NULL; // Reset rear if queue is now empty
}
free(temp);
}
Time Complexity:
Enqueue: O(1) (constant time).
4. Real-World Systems:
Ticket Counters: Customers are served in arrival order.
Call Centers: Callers wait in a queue for the next available agent.
5. Data Buffering:
Streaming Services: Frames are buffered in queues for smooth playback.
Example Scenarios:
Application Queue Usage
CPU Scheduling Manages processes waiting for CPU time.
BFS Algorithm Tracks nodes to visit next in a graph.
Print Spooler Orders print jobs to avoid conflicts.
Key Points:
Queues ensure orderly processing in time-sensitive systems.
Used where FIFO service is critical (e.g., scheduling, buffering).
Key Takeaways
Queue Operations:
Applications:
OS, Networking, BFS, and real-world systems rely on queues for FIFO management.
22. B-Tree of Order 5: Insertion of 81, 7, 49, 61, and 30 (10 Marks)
B-Tree Properties (Order 5):
Maximum Keys per Node: 4 (since order m = 5 m-1 keys).
Initial B-Tree:
(Assume an empty tree or provide the initial structure if given.)
Step-by-Step Insertions:
Insert 81:
text
[81]
Insert 7:
text
[7, 81]
Insert 49:
text
[7, 49, 81]
Insert 61:
text
[7, 49, 61, 81]
Insert 30:
text
[49]
/ \
[7, 30] [61, 81]
Final B-Tree After Insertions:
text
[49]
/ \
[7, 30] [61, 81]
C Code for B-Tree Insertion (Simplified for Order 5):
c
#include <stdio.h>
#include <stdlib.h>
#define MAX_KEYS 4
struct BTreeNode {
int keys[MAX_KEYS];
struct BTreeNode *children[MAX_KEYS + 1];
int num_keys;
int is_leaf;
};
int main() {
int keys[] = {81, 7, 49, 61, 30};
for (int i = 0; i < 5; i++) {
insert(keys[i]);
}
printf("B-Tree after insertions: ");
printBTree(root);
return 0;
}
Output:
text
B-Tree after insertions: 7 30 49 61 81
Key Points:
Splitting Nodes:
When a node exceeds 4 keys, it splits into two nodes, promoting the median key.
Balanced Structure:
Time Complexity:
No two adjacent Red nodes (Red node cannot have a Red parent or child).
Every path from a node to its descendant NULL leaves has the same number of Black nodes.
Insertion Operation:
Steps:
text
10(B)
Insert 20 (Red, no violation).
text
10(B)
\
20(R)
Insert 30 (Violation: Two Reds in a row).
text
20(B)
/ \
10(R) 30(R)
text
---
---
### **23(b) Depth-First Search (DFS) Algorithm in C (5 Marks)**
#### **Algorithm**:
1. **Start** at a node, mark it as visited.
2. **Recursively visit** all unvisited adjacent nodes.
struct Node {
int vertex;
struct Node* next;
};
struct Graph {
int numVertices;
struct Node** adjLists;
};
// Create a node
struct Node* createNode(int v) {
struct Node* newNode = malloc(sizeof(struct Node));
newNode->vertex = v;
newNode->next = NULL;
return newNode;
}
// Create a graph
struct Graph* createGraph(int vertices) {
struct Graph* graph = malloc(sizeof(struct Graph));
graph->numVertices = vertices;
graph->adjLists = malloc(vertices * sizeof(struct Node*));
for (int i = 0; i < vertices; i++) {
graph->adjLists[i] = NULL;
visited[i] = 0; // Initialize as unvisited
}
return graph;
}
// Add edge
void addEdge(struct Graph* graph, int src, int dest) {
struct Node* newNode = createNode(dest);
newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;
}
// DFS function
void DFS(struct Graph* graph, int vertex) {
visited[vertex] = 1;
printf("Visited %d\n", vertex);
struct Node* temp = graph->adjLists[vertex];
while (temp != NULL) {
int adjVertex = temp->vertex;
if (!visited[adjVertex]) {
DFS(graph, adjVertex);
}
temp = temp->next;
}
}
int main() {
struct Graph* graph = createGraph(4);
addEdge(graph, 0, 1);
addEdge(graph, 0, 2);
addEdge(graph, 1, 2);
addEdge(graph, 2, 3);
printf("DFS Traversal:\n");
DFS(graph, 0); // Start from vertex 0
return 0;
}
Output:
text
DFS Traversal:
Visited 0
Visited 2
Visited 3
Visited 1
Time Complexity:
O(V + E) (V = vertices, E = edges).
Key Takeaways
Red-Black Tree:
DFS: