ISC Computer Science · Class XII

Data Structures
Complete Study Guide

// Stack · Queue · Linked List · Binary Trees · Infix/Prefix/Postfix

Exam: 27 March 2026 · You've got this! 🚀
📚 Data Structures Overview
// Start here — understand the big picture
🧩What is a Data Structure?
A data structure is a way of organizing, storing, and managing data in a computer so that it can be accessed and modified efficiently. It defines the relationship between data elements and the operations that can be performed on them.

Every data structure has:

  • Definition — what it is (mathematical/logical)
  • Interface (ADT) — what operations are supported
  • Implementation — how operations work in code
📋Abstract Data Type (ADT)

An Abstract Data Type (ADT) is a mathematical model for a data type that defines its behavior purely from the user's point of view — specifying the type of data and the operations possible, without specifying how these operations will be implemented.

Key idea: ADT = Data + Operations (no implementation details). In Java, we use the interface keyword to define ADTs.
🗺️ISC Syllabus Map
TopicKey ConceptsWeight
Stack LIFO, push, pop, peek, isEmpty, overflow/underflow High ⭐⭐⭐
Queue FIFO, enqueue, dequeue, circular queue, dequeue (double-ended) High ⭐⭐⭐
Infix/Postfix/Prefix Conversion algorithms using stack, precedence rules Very High ⭐⭐⭐⭐
Linked List Insertion, deletion, reversal, traversal, searching High ⭐⭐⭐
Binary Trees Terminology, properties, traversals (conceptual) High ⭐⭐⭐
Interface & ADT Java interface, multiple implementations Medium ⭐⭐
🥞 Stack
// Last In, First Out (LIFO)
📖Definition
A Stack is a linear data structure that follows the LIFO (Last In, First Out) principle. The element inserted last is the first to be removed. Think of a stack of plates — you add and remove from the top only.
PUSH ↓ POP ↑ ┌─────────┐ TOP →│ 40 ← TOP ← most recently added ├─────────┤ │ 30 │ ├─────────┤ │ 20 │ ├─────────┤ BOTTOM →│ 10 │ ← first element added └─────────┘
⚙️Stack Operations (ADT Interface)
OperationDescriptionCondition Check
push(x)Insert element x onto top of stackCheck: not full (overflow)
pop()Remove and return top elementCheck: not empty (underflow)
peek() / top()Return top element without removingCheck: not empty
isEmpty()Returns true if stack has no elements
isFull()Returns true if stack is at max capacityArray-based only
size()Returns number of elements
Stack Overflow: Attempt to push onto a full stack.
Stack Underflow: Attempt to pop from an empty stack.
💻Java Implementation (Array-based)
// Stack interface (ADT)
interface Stack {
    void push(int x);
    int  pop();
    int  peek();
    boolean isEmpty();
    boolean isFull();
}

// Array-based implementation
class ArrayStack implements Stack {
    int[] arr;
    int top, maxSize;

    ArrayStack(int size) {
        maxSize = size;
        arr = new int[maxSize];
        top = -1;  // -1 means empty
    }

    public boolean isEmpty() { return top == -1; }
    public boolean isFull()  { return top == maxSize - 1; }

    public void push(int x) {
        if (isFull())
            System.out.println("Stack Overflow!");
        else
            arr[++top] = x;
    }

    public int pop() {
        if (isEmpty()) {
            System.out.println("Stack Underflow!");
            return -1;
        }
        return arr[top--];
    }

    public int peek() {
        if (isEmpty()) return -1;
        return arr[top];
    }
}Java
🌍Applications of Stack
  • Expression conversion — Infix to Postfix/Prefix
  • Expression evaluation — Evaluating Postfix expressions
  • Function call stack — Recursion management
  • Undo operation — In text editors
  • Balanced parentheses checking
  • Browser history — Back button
🚶 Queue, Circular Queue & Dequeue
// First In, First Out (FIFO)
📖Simple Queue — Definition
A Queue is a linear data structure that follows the FIFO (First In, First Out) principle. Insertions happen at the REAR and deletions happen at the FRONT. Like a real-world queue (line).
ENQUEUE → REAR FRONT → DEQUEUE ┌────┬────┬────┬────┬────┐ │ 10 │ 20 │ 30 │ 40 │ 50 │ └────┴────┴────┴────┴────┘ REAR=4 FRONT=0
OperationDescription
enqueue(x)Add element at REAR
dequeue()Remove element from FRONT
peek()View FRONT element without removing
isEmpty()front == -1 (or front > rear)
isFull()rear == maxSize - 1
Problem with simple queue: Even if front has moved (spaces freed), rear can't go back — space is wasted! This is solved by Circular Queue.
🔄Circular Queue
A Circular Queue (Ring Buffer) connects the last position back to the first position — forming a circle. It solves the wasted space problem of simple queue.
┌────┐ ┌──→ │ 10 │ ←──FRONT │ ├────┤ │ │ 20 │ │ ├────┤ │ │ 30 │ ←──REAR │ ├────┤ └─── │ │ (free) └────┘ front = (front+1) % maxSize rear = (rear+1) % maxSize

Key Formulae (Circular Queue)

  • Enqueue: rear = (rear + 1) % maxSize
  • Dequeue: front = (front + 1) % maxSize
  • Empty: front == -1
  • Full: (rear + 1) % maxSize == front
class CircularQueue {
    int[] arr;
    int front, rear, maxSize;

    CircularQueue(int size) {
        maxSize = size;
        arr = new int[maxSize];
        front = rear = -1;
    }

    boolean isEmpty() { return front == -1; }

    boolean isFull() {
        return (rear + 1) % maxSize == front;
    }

    void enqueue(int x) {
        if (isFull()) { System.out.println("Queue Full!"); return; }
        if (isEmpty()) front = 0;
        rear = (rear + 1) % maxSize;
        arr[rear] = x;
    }

    int dequeue() {
        if (isEmpty()) { System.out.println("Queue Empty!"); return -1; }
        int val = arr[front];
        if (front == rear) front = rear = -1; // last element removed
        else front = (front + 1) % maxSize;
        return val;
    }
}Java
↔️Dequeue (Double-Ended Queue)
A Dequeue (Deque) — Double-Ended Queue — allows insertions and deletions from both ends (front and rear).
Input-Restricted Deque:
Insertion allowed only at one end, deletion at both ends.
Output-Restricted Deque:
Deletion allowed only at one end, insertion at both ends.
OperationDescription
insertFront(x)Add at front
insertRear(x)Add at rear
deleteFront()Remove from front
deleteRear()Remove from rear
peekFront()View front element
peekRear()View rear element
📊Queue vs Stack vs Dequeue
PropertyStackQueueDequeue
OrderLIFOFIFOBoth ends
Insert atTOP onlyREAR onlyBoth ends
Delete fromTOP onlyFRONT onlyBoth ends
UsesRecursion, UndoScheduling, BFSPalindrome check
🔁 Infix, Prefix & Postfix
// Expression Notations — Most Important for Exam!
📖Three Notations Defined
NotationOperator PositionExample (A+B)Also Called
Infix Between operands A + B Normal / Human notation
Prefix Before operands + A B Polish Notation
Postfix After operands A B + Reverse Polish Notation (RPN)
Why do we need postfix/prefix? Computers process these notations without needing parentheses or operator precedence rules — making them efficient for expression evaluation.
📐Operator Precedence & Associativity
PrecedenceOperator(s)Associativity
1 (Highest)( ) Parentheses
2^ ExponentiationRight to Left
3* / Multiply, DivideLeft to Right
4 (Lowest)+ - Add, SubtractLeft to Right
🔄Infix to Postfix — Algorithm (Stack-based)
  1. Scan expression left to right
  2. If it's an operand, add to output
  3. If it's a '(', push onto stack
  4. If it's a ')', pop from stack to output until '(' is found; discard '('
  5. If it's an operator: pop operators from stack with greater or equal precedence to output, then push current operator
  6. At end, pop all remaining operators from stack to output
Exception for '^': Since it is right-associative, pop only operators with strictly greater precedence (not equal).
📝Infix to Postfix — Worked Example

Convert: A + B * C - D

CharacterStackOutputAction
A[ ]AOperand → output
+[+]APush +
B[+]ABOperand → output
*[+,*]AB* has higher precedence, push
C[+,*]ABCOperand → output
-[-]ABC*+Pop * and + (≥ precedence), push -
D[-]ABC*+DOperand → output
End[ ]ABC*+D-Pop remaining -
Result: A B C * + D -
📝More Examples — Quick Reference
InfixPostfixPrefix
A + BA B ++ A B
A + B * CA B C * ++ A * B C
(A + B) * CA B + C ** + A B C
A * B + C * DA B * C D * ++ * A B * C D
A ^ B ^ CA B C ^ ^^ A ^ B C
(A + B) * (C - D)A B + C D - ** + A B - C D
🔄Infix to Prefix — Algorithm
  1. Reverse the infix expression
  2. Swap '(' with ')' and vice versa in the reversed expression
  3. Apply the Infix to Postfix algorithm on this modified expression
  4. Reverse the resulting postfix expression to get prefix
Alternative: Fully parenthesize the infix expression, then move each operator to the position of its corresponding left parenthesis, then remove all parentheses.
💻Postfix Evaluation Using Stack

Algorithm

  1. Scan postfix expression left to right
  2. If operand, push onto stack
  3. If operator, pop two operands (b then a), compute a op b, push result
  4. Final result is left on top of stack

Example: Evaluate 5 3 2 * + 1 -

Scan 5 → push 5     Stack: [5]
Scan 3 → push 3     Stack: [5,3]
Scan 2 → push 2     Stack: [5,3,2]
Scan * → pop 2,3 → 3*2=6, push 6   Stack: [5,6]
Scan + → pop 6,5 → 5+6=11, push 11 Stack: [11]
Scan 1 → push 1     Stack: [11,1]
Scan - → pop 1,11 → 11-1=10, push 10

Result: 10
🔗 Single Linked List
// Dynamic linear data structure
📖Definition & Structure
A Linked List is a linear data structure where elements (called nodes) are stored at non-contiguous memory locations and each node contains a data field and a pointer/reference to the next node.
HEAD ↓ ┌──────┬────┐ ┌──────┬────┐ ┌──────┬──────┐ │ 10 │ •──┼───→│ 20 │ •──┼───→│ 30 │ null │ └──────┴────┘ └──────┴────┘ └──────┴──────┘ Node 1 Node 2 Node 3 (tail)

Node Structure in Java

class Node {
    int data;
    Node next;

    Node(int d) {
        data = d;
        next = null;
    }
}Java
Insertion Operations

New node's next points to current head; head updated to new node.

void insertAtBeginning(int data) {
    Node newNode = new Node(data);
    newNode.next = head;  // point to old head
    head = newNode;       // update head
}
New→[data|•]→[old head]→...→null

Traverse to last node, set its next to new node.

void insertAtEnd(int data) {
    Node newNode = new Node(data);
    if (head == null) { head = newNode; return; }
    Node temp = head;
    while (temp.next != null)
        temp = temp.next;
    temp.next = newNode;
}

Traverse to node before desired position, redirect pointers.

void insertAtPosition(int data, int pos) {
    Node newNode = new Node(data);
    if (pos == 1) { newNode.next = head; head = newNode; return; }
    Node temp = head;
    for (int i = 1; i < pos - 1 && temp != null; i++)
        temp = temp.next;
    newNode.next = temp.next;
    temp.next = newNode;
}
Deletion Operations
void deleteFirst() {
    if (head == null) { System.out.println("Empty!"); return; }
    head = head.next;  // move head forward
}
void deleteLast() {
    if (head == null) return;
    if (head.next == null) { head = null; return; }
    Node temp = head;
    while (temp.next.next != null)
        temp = temp.next;
    temp.next = null;  // remove last node
}
void deleteByValue(int val) {
    if (head == null) return;
    if (head.data == val) { head = head.next; return; }
    Node temp = head;
    while (temp.next != null && temp.next.data != val)
        temp = temp.next;
    if (temp.next != null)
        temp.next = temp.next.next;
}
🔃Reversal of Linked List
Classic interview question! Three pointer technique.
void reverse() {
    Node prev = null;
    Node curr = head;
    Node next = null;

    while (curr != null) {
        next = curr.next;   // save next
        curr.next = prev;   // reverse pointer
        prev = curr;        // move prev forward
        curr = next;        // move curr forward
    }
    head = prev;  // new head is old tail
}Java
Before: 1 → 2 → 3 → 4 → null After: 4 → 3 → 2 → 1 → null
🔍Other Operations

Check Emptiness

boolean isEmpty() {
    return head == null;
}

Display / Traverse

void display() {
    Node t = head;
    while (t != null) {
        System.out.print(t.data+" → ");
        t = t.next;
    }
    System.out.println("null");
}

Extract Element at Position

int getElement(int pos) {
    Node temp = head;
    for (int i = 1; i < pos && temp != null; i++)
        temp = temp.next;
    return (temp != null) ? temp.data : -1;
}

Array vs Linked List Comparison

FeatureArrayLinked List
SizeFixed at creationDynamic
MemoryContiguousNon-contiguous
AccessO(1) randomO(n) sequential
InsertionO(n) shiftingO(1) at known position
DeletionO(n) shiftingO(1) at known position
🌳 Binary Trees
// Hierarchical data structure — Conceptual + Traversals
📖Definition
A Binary Tree is a hierarchical data structure in which each node has at most two children, referred to as the left child and the right child.
A ← ROOT (Level 0 / Depth 0) / \ B C ← Level 1 / \ / \ D E F G ← Level 2 (Leaves) A = Root, Internal nodes = {A, B, C} Leaves (External) = {D, E, F, G}
📚Complete Terminology — All You Must Know
TermDefinitionExample (above tree)
RootTopmost node; has no parentA
Internal NodeNode with at least one childA, B, C
External Node (Leaf)Node with no childrenD, E, F, G
ParentNode with child nodesA is parent of B, C
ChildNodes directly below a parentB, C are children of A
SiblingsNodes sharing the same parentB & C are siblings; D & E are siblings
SubtreeA node and all its descendantsB's subtree = {B, D, E}
EdgeConnection between parent and childA→B, A→C, etc.
PathSequence of nodes from one to anotherA→B→D
LevelDistance from root + 1 (root = level 1)A=1, B&C=2, D,E,F,G=3
Depth of NodeNumber of edges from root to nodedepth(A)=0, depth(B)=1, depth(D)=2
Height of NodeNumber of edges on longest path from node to a leafheight(A)=2, height(B)=1, height(D)=0
Height of TreeHeight of root = max depth of any leafHeight = 2
Depth of TreeSame as height of tree2
Degree of NodeNumber of children of that nodedegree(A)=2, degree(D)=0
Degree of TreeMaximum degree of any node2 (binary tree)
SizeTotal number of nodes in tree7
🏗️Types of Binary Trees
Full Binary Tree
Every node has either 0 or 2 children. No node has exactly 1 child.
Complete Binary Tree
All levels completely filled except possibly the last, which is filled from left to right.
Perfect Binary Tree
All internal nodes have exactly 2 children and all leaves are at the same level.
Degenerate (Skewed) Tree
Every internal node has only one child. Essentially a linked list.

Balanced Binary Tree

A tree is balanced if for every node, the height difference between the left and right subtrees is at most 1 (|height(left) - height(right)| ≤ 1). Example: AVL Tree.
🚶Tree Traversals — The Most Exam-Asked Topic!
Traversal means visiting every node exactly once. There are 3 standard depth-first traversals.
1 / \ 2 3 / \ / \ 4 5 6 7

1. Inorder Traversal — Left → Root → Right

Visit left subtree, then root, then right subtree.

Result for above tree: 4 → 2 → 5 → 1 → 6 → 3 → 7
Key property: Inorder traversal of a BST gives sorted ascending order.
void inorder(Node root) {
    if (root == null) return;
    inorder(root.left);    // Left
    System.out.print(root.data + " ");  // Root
    inorder(root.right);   // Right
}

2. Preorder Traversal — Root → Left → Right

Visit root first, then left subtree, then right subtree.

Result: 1 → 2 → 4 → 5 → 3 → 6 → 7
Use: Copying/Printing the tree structure; creating a prefix expression.
void preorder(Node root) {
    if (root == null) return;
    System.out.print(root.data + " ");  // Root
    preorder(root.left);   // Left
    preorder(root.right);  // Right
}

3. Postorder Traversal — Left → Right → Root

Visit left subtree, right subtree, then root last.

Result: 4 → 5 → 2 → 6 → 7 → 3 → 1
Use: Deleting a tree; evaluating postfix expression trees.
void postorder(Node root) {
    if (root == null) return;
    postorder(root.left);   // Left
    postorder(root.right);  // Right
    System.out.print(root.data + " ");  // Root
}

Memory Trick

Inorder = Left INside Right (LNR)
Preorder = PREfix = Root first (NLR)
Postorder = POSTfix = Root last (LRN)

N = Node/Root, L = Left, R = Right
🌟Important Properties of Binary Trees
  • Max nodes at level l = 2l (where root is level 0)
  • Max nodes in tree of height h = 2h+1 − 1
  • Min height for n nodes = ⌊log₂n⌋
  • In a full binary tree: leaves = internal nodes + 1
  • A complete binary tree with n nodes has height = ⌊log₂n⌋
🔌 Interface & ADT in Java
// Define once, implement many ways
📖Java Interface as ADT
A Java interface perfectly models an ADT — it declares what operations exist but not how they work. Multiple classes can implement the same interface differently.
// Stack ADT defined as interface
interface StackADT {
    void    push(int x);
    int     pop();
    int     peek();
    boolean isEmpty();
    int     size();
}

// Implementation 1: using array
class ArrayStack implements StackADT {
    int[] arr = new int[100];
    int top = -1;

    public void push(int x) { arr[++top] = x; }
    public int  pop()       { return arr[top--]; }
    public int  peek()      { return arr[top]; }
    public boolean isEmpty() { return top == -1; }
    public int  size()      { return top + 1; }
}

// Implementation 2: using linked list node
class LinkedStack implements StackADT {
    private class Node {
        int data; Node next;
        Node(int d) { data = d; }
    }
    Node top = null;
    int count = 0;

    public void push(int x) {
        Node n = new Node(x);
        n.next = top; top = n; count++;
    }
    public int pop() {
        int v = top.data; top = top.next; count--; return v;
    }
    public int     peek()    { return top.data; }
    public boolean isEmpty() { return top == null; }
    public int     size()    { return count; }
}

// Usage with polymorphism
StackADT s1 = new ArrayStack();
StackADT s2 = new LinkedStack();
// Both can be used the same way!Java
🔑Key Points about Java Interface
  • All methods in an interface are implicitly public and abstract
  • A class uses implements keyword to implement an interface
  • A class must override all methods of the interface
  • One class can implement multiple interfaces
  • Interface references can hold objects of implementing classes (polymorphism)
  • Interfaces cannot be instantiated directly
ISC Exam tip: Know how to write an interface for Stack and Queue, then implement it both ways (array and linked list).
🧠 Practice Quiz
// Test your understanding — click options to check answers
Q1. A stack follows which principle?
A stack uses LIFO. The last element pushed is the first to be popped. FILO is just an alternate name for the same — so LIFO is the standard answer.
Q2. What is the Postfix form of: (A + B) * C?
(A+B)*C → first evaluate (A+B) → A B +, then multiply by C → A B + C *. Postfix: A B + C *
Q3. In a Circular Queue of size 5, if front=2 and rear=4, what is the position after enqueue?
rear = (rear+1) % maxSize = (4+1) % 5 = 5 % 5 = 0. This is the circular wraparound!
Q4. Which traversal of a BST gives elements in sorted order?
Inorder traversal (Left → Node → Right) of a Binary Search Tree always produces elements in ascending sorted order.
Q5. What is the height of a single node tree?
Height of a node = number of edges on the longest path from that node to a leaf. A single node (root = leaf) has height 0.
Q6. In Linked List insertion at beginning, what is the first step?
You must first link the new node to the current head (newNode.next = head), THEN update head = newNode. If you update head first, you lose the old list!
Q7. What does a Dequeue (Double-Ended Queue) allow?
A Dequeue (Double Ended Queue) supports insertion and deletion from BOTH ends — making it more flexible than both stack and queue.
Q8. Postorder traversal of the tree with root=A, A→B (left), A→C (right), B→D (left), B→E (right) is:
Postorder = LRN. For B: D(L)→E(R)→B(N) = D,E,B. Then C (leaf). Then root A. Full: D E B C A