Data Structures Exam Notes

Unit III & IV - Complete Study Guide

Quick Reference

Part A: 2 Marks Questions

1. Difference between Double Linked List and Array

Feature Array Double Linked List
MemoryContiguousNon-contiguous
SizeFixedDynamic
AccessRandom (O(1))Sequential (O(n))
InsertionCostly (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

  1. Every node is Red or Black
  2. Root is always Black
  3. All leaves (NULL) are Black
  4. If node is Red, both children must be Black
  5. Every path has same count of Black nodes
  6. 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;
    }
}
OperationTime ComplexitySpace Complexity
Insertion at EndO(n)O(1)
Before: NULL ← [Head] ↔ [Node2] ↔ [Last] → NULL After: NULL ← [Head] ↔ [Node2] ↔ [Last] ↔ [New] → NULL

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);
}
OperationTime ComplexitySpace Complexity
PushO(1)O(1)
PopO(1)O(1)
PeekO(1)O(1)

3. AVL Tree Insertion with Example

Steps: 1) BST Insertion 2) Update heights 3) Check Balance Factor 4) Rotate if needed

Insert: 10, 20, 30 Step 1: 10 (BF=0) Step 2: 10 (BF=-1) \ 20 (BF=0) Step 3: 10 (BF=-2) ← Unbalanced \ 20 (BF=-1) \ 30 (BF=0) After RR Rotation: 20 (BF=0) / \ 10 (BF=0) 30 (BF=0)
OperationTime ComplexitySpace Complexity
InsertionO(log n)O(1)
SearchO(log n)O(1)
DeletionO(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);
}
TraversalTime ComplexitySpace Complexity
In-OrderO(n)O(h)
Pre-OrderO(n)O(h)
Post-OrderO(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;
}
OperationTime ComplexitySpace Complexity
Insert at BeginningO(1)O(1)
Insert at EndO(n)O(1)
Insert AfterO(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

50 / \ 30 70 / \ / \ 20 40 60 80
OperationTime ComplexitySpace Complexity
ConstructionO(n log n) avg, O(n²) worstO(n)
SearchO(log n) avg, O(n) worstO(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;
}
Insert 15 into: 10 \ 20 Result: 10 \ 20 / 15

8. BST Deletion (3 Cases)

Case 1: Delete Leaf Node

Before: After: 50 50 / \ / \ 30 70 → 30 70 / \ 60 [80] (80 deleted)

Case 2: Delete Node with One Child

Before: After: 50 50 / \ / \ 30 70 → 30 60 / 60 (70 deleted, 60 moves up)

Case 3: Delete Node with Two Children

Before: After: 50 60 / \ / \ 30 70 → 50 70 / \ / 60 80 30 (Delete 50, replace with inorder successor 60)
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;
}
OperationTime ComplexitySpace Complexity
DeletionO(log n) avg, O(n) worstO(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);
}
OperationTime ComplexitySpace Complexity
EnqueueO(1)O(1)
DequeueO(1)O(1)
PeekO(1)O(1)
Queue Structure: front → [Node1] → [Node2] → [Node3] ← rear

Quick Reference

Complexity Summary

Data Structure Search Insert Delete
ArrayO(1)O(n)O(n)
Linked ListO(n)O(1)*O(1)*
BSTO(log n)O(log n)O(log n)
AVL TreeO(log n)O(log n)O(log n)
Stack/QueueO(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 ≥ 0Right Rotate
Right-Right (RR)BF < -1, right child BF ≤ 0Left Rotate
Left-Right (LR)BF > 1, left child BF < 0Left then Right
Right-Left (RL)BF < -1, right child BF > 0Right then Left

Threaded Binary Tree

Aspect Details
DefinitionBinary tree where NULL pointers point to inorder predecessor/successor
AdvantagesNo recursion/stack needed for traversal, faster inorder traversal
DisadvantagesComplex insertion/deletion, extra memory for thread flags
TypesSingle 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

Quick Checklist Before Submitting