Data Structures Exam Notes
Unit III & IV - Complete Study Guide
Part A: 2 Marks Questions
1. Difference between Double Linked List and Array
| Feature | Array | Double Linked List |
|---|---|---|
| Memory | Contiguous | Non-contiguous |
| Size | Fixed | Dynamic |
| Access | Random (O(1)) | Sequential (O(n)) |
| Insertion | Costly (O(n)) | Efficient (O(1)) |
2. Single, Double, Circular Linked List
Single LL
Nodes have data and next pointer. One-way traversal.
Double LL
Nodes have data, prev, and next. Two-way traversal.
Circular LL
Last node points to head instead of NULL.
Basic Operations: Insertion, Deletion, Traversal
3. Double Linked List Node Structure
struct Node {
int data;
struct Node* previous;
struct Node* next;
};
Three fields: data, previous pointer, next pointer
4. Strictly Binary Tree (Full Binary Tree)
Every node has either 0 children (leaf) or exactly 2 children. No node has 1 child.
Formula: If internal nodes = n, leaf nodes = n + 1
5. Properties of Red-Black Tree
- Every node is Red or Black
- Root is always Black
- All leaves (NULL) are Black
- If node is Red, both children must be Black
- Every path has same count of Black nodes
- New nodes inserted as Red
6. AVL Tree Definition
Height-Balanced Binary Search Tree where Balance Factor of every node is -1, 0, or +1.
Balance Factor: Height(Left) - Height(Right)
7. AVL Tree Rotations
LL Rotation
Single clockwise (Left-Left case)
RR Rotation
Single anticlockwise (Right-Right case)
LR Rotation
Double rotation (Left-Right case)
RL Rotation
Double rotation (Right-Left case)
Part B: 5-10 Marks Questions
1. Double Linked List: Insertion at End
void insertAtEnd(int value) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = value;
newNode->next = NULL;
if(head == NULL) {
newNode->previous = NULL;
head = newNode;
} else {
struct Node* temp = head;
while(temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
newNode->previous = temp;
}
}
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Insertion at End | O(n) | O(1) |
2. Stack Using Linked List
Implements LIFO (Last In First Out). Top pointer points to most recent node.
struct Node {
int data;
struct Node* next;
}*top = NULL;
void push(int value) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode == NULL) {
printf("Stack Overflow\n");
return;
}
newNode->data = value;
newNode->next = top;
top = newNode;
}
void pop() {
if(top == NULL) {
printf("Stack Underflow\n");
return;
}
struct Node* temp = top;
top = temp->next;
free(temp);
}
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Push | O(1) | O(1) |
| Pop | O(1) | O(1) |
| Peek | O(1) | O(1) |
3. AVL Tree Insertion with Example
Steps: 1) BST Insertion 2) Update heights 3) Check Balance Factor 4) Rotate if needed
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Insertion | O(log n) | O(1) |
| Search | O(log n) | O(1) |
| Deletion | O(log n) | O(1) |
4. Binary Tree Traversal
In-Order
Left → Root → Right
Use: Sorted output in BST
Pre-Order
Root → Left → Right
Use: Copy tree
Post-Order
Left → Right → Root
Use: Delete tree
void inorder(struct Node* root) {
if(root == NULL) return;
inorder(root->left);
printf("%d ", root->data);
inorder(root->right);
}
| Traversal | Time Complexity | Space Complexity |
|---|---|---|
| In-Order | O(n) | O(h) |
| Pre-Order | O(n) | O(h) |
| Post-Order | O(n) | O(h) |
5. Single Linked List: Insertion Operations
// Insert at Beginning - O(1)
void insertAtBeginning(int value) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode == NULL) return;
newNode->data = value;
newNode->next = head;
head = newNode;
}
// Insert at End - O(n)
void insertAtEnd(int value) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode == NULL) return;
newNode->data = value;
newNode->next = NULL;
if(head == NULL) {
head = newNode;
return;
}
struct Node* temp = head;
while(temp->next != NULL) temp = temp->next;
temp->next = newNode;
}
// Insert After Location - O(n)
void insertAfter(int value, int location) {
if(head == NULL) return;
struct Node* temp = head;
while(temp != NULL && temp->data != location) {
temp = temp->next;
}
if(temp == NULL) return; // Location not found
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode == NULL) return;
newNode->data = value;
newNode->next = temp->next;
temp->next = newNode;
}
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Insert at Beginning | O(1) | O(1) |
| Insert at End | O(n) | O(1) |
| Insert After | O(n) | O(1) |
6. Construct Binary Search Tree
Rule: First value = Root. If value < Root → Left. If value > Root → Right.
Problem: Construct BST for: 50, 30, 70, 20, 40, 60, 80
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Construction | O(n log n) avg, O(n²) worst | O(n) |
| Search | O(log n) avg, O(n) worst | O(1) |
7. Tree Insertion Algorithm
struct Node* insert(struct Node* node, int key) {
if(node == NULL) {
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
if(temp == NULL) return NULL;
temp->data = key;
temp->left = temp->right = NULL;
return temp;
}
if(key < node->data)
node->left = insert(node->left, key);
else if(key > node->data)
node->right = insert(node->right, key);
return node;
}
8. BST Deletion (3 Cases)
Case 1: Delete Leaf Node
Case 2: Delete Node with One Child
Case 3: Delete Node with Two Children
struct Node* deleteNode(struct Node* root, int key) {
if(root == NULL) return NULL;
if(key < root->data)
root->left = deleteNode(root->left, key);
else if(key > root->data)
root->right = deleteNode(root->right, key);
else {
// Node found
if(root->left == NULL) {
struct Node* temp = root->right;
free(root);
return temp;
}
else if(root->right == NULL) {
struct Node* temp = root->left;
free(root);
return temp;
}
// Two children: Get inorder successor
struct Node* temp = minValueNode(root->right);
root->data = temp->data;
root->right = deleteNode(root->right, temp->data);
}
return root;
}
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Deletion | O(log n) avg, O(n) worst | O(h) |
9. Queue Using Linked List
Implements FIFO (First In First Out). Uses front and rear pointers.
struct Node {
int data;
struct Node* next;
};
struct Queue {
struct Node *front, *rear;
};
void enqueue(struct Queue* q, int value) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode == NULL) {
printf("Queue Overflow\n");
return;
}
newNode->data = value;
newNode->next = NULL;
if(q->rear == NULL) {
q->front = q->rear = newNode;
return;
}
q->rear->next = newNode;
q->rear = newNode;
}
void dequeue(struct Queue* q) {
if(q->front == NULL) {
printf("Queue Underflow\n");
return;
}
struct Node* temp = q->front;
q->front = q->front->next;
if(q->front == NULL) q->rear = NULL;
free(temp);
}
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Enqueue | O(1) | O(1) |
| Dequeue | O(1) | O(1) |
| Peek | O(1) | O(1) |
Quick Reference
Complexity Summary
| Data Structure | Search | Insert | Delete |
|---|---|---|---|
| Array | O(1) | O(n) | O(n) |
| Linked List | O(n) | O(1)* | O(1)* |
| BST | O(log n) | O(log n) | O(log n) |
| AVL Tree | O(log n) | O(log n) | O(log n) |
| Stack/Queue | O(n) | O(1) | O(1) |
*At beginning if pointer available
Important Formulas
Full Binary Tree: Leaves = Internal + 1
Max nodes at level h: 2^h
Max nodes in tree height h: 2^(h+1) - 1
AVL Balance Factor: H(left) - H(right)
Min nodes AVL height h: N(h) = N(h-1) + N(h-2) + 1
Height of AVL with n nodes: 1.44 log₂(n+2) - 1.328
AVL Rotation Triggers
| Case | Balance Factor | Rotation |
|---|---|---|
| Left-Left (LL) | BF > 1, left child BF ≥ 0 | Right Rotate |
| Right-Right (RR) | BF < -1, right child BF ≤ 0 | Left Rotate |
| Left-Right (LR) | BF > 1, left child BF < 0 | Left then Right |
| Right-Left (RL) | BF < -1, right child BF > 0 | Right then Left |
Threaded Binary Tree
| Aspect | Details |
|---|---|
| Definition | Binary tree where NULL pointers point to inorder predecessor/successor |
| Advantages | No recursion/stack needed for traversal, faster inorder traversal |
| Disadvantages | Complex insertion/deletion, extra memory for thread flags |
| Types | Single threaded, Double threaded |
Practice Problems
AVL Tree Insertion Problems
Problem 1:
Insert: 10, 20, 30, 40, 50, 25
Solution: RR rotation at 10, then LR at 30
Problem 2:
Insert: 50, 30, 70, 20, 40, 35, 45
Solution: LL rotation at 50
Problem 3:
Insert: 100, 50, 150, 25, 75, 125, 175, 60
Solution: RR rotation at 50
Problem 4:
Insert: 30, 20, 10, 25, 5, 15
Solution: LL rotation at 30, then RL at 20
Problem 5:
Insert: 15, 10, 20, 8, 12, 17, 25
Solution: Balanced tree, no rotation needed
BST Construction Problems
Problem 1:
Construct BST: 45, 30, 60, 20, 40, 55, 70
Solution: 45 root, 30 left, 60 right, etc.
Problem 2:
Construct BST: 100, 50, 150, 25, 75, 125, 175
Solution: Perfectly balanced BST
Problem 3:
Construct BST: 10, 5, 15, 3, 7, 12, 20
Solution: 10 root, 5 left subtree, 15 right subtree
Problem 4:
Construct BST: 80, 40, 120, 20, 60, 100, 140
Solution: 80 root, complete binary tree structure
Problem 5:
Construct BST: 25, 15, 35, 10, 20, 30, 40
Solution: 25 root, balanced structure
Linked List Tracing Problems
Problem 1:
Trace: Insert 5, 10, 15 at beginning of empty SLL
Solution: 15 → 10 → 5 → NULL
Problem 2:
Trace: Delete node with value 10 from 5 → 10 → 15
Solution: 5 → 15 → NULL
Problem 3:
Trace: Insert 20 after 10 in list 5 → 10 → 15
Solution: 5 → 10 → 20 → 15 → NULL
Exam Writing Tips
Mark Distribution
- 2 Marks: Definition + 2-3 points (50 words)
- 5 Marks: Algorithm + Diagram + Example (150 words)
- 10 Marks: Complete algorithm + Code + Diagram + Complexity + Example (300 words)
What Examiners Look For
- ✓ Clear diagrams with labels
- ✓ Proper algorithm steps
- ✓ Time/Space complexity mentioned
- ✓ Working code with error handling
- ✓ Neat presentation with headings
Common Mistakes to Avoid
✗ Forgetting NULL checks in code
✗ Not mentioning complexity
✗ Drawing unclear diagrams
✗ Missing edge cases in algorithms
✗ Not showing before/after states
✗ Writing incomplete code