This page has been replaced by the new Data Structures sub-page structure. Content is preserved here for reference while sub-pages are built out.

Data Structures

IB Syllabus: B2.2 — Data structures

Table of Contents

  1. Static vs Dynamic Structures
  2. 1D Arrays
    1. Declaring and Initialising
    2. Array Length
    3. Traversal
  3. Common Array Operations
    1. Find Maximum and Minimum
    2. Sum and Average
    3. Count Occurrences
    4. Duplicate Detection
  4. Copying Arrays
    1. The Reference Trap
    2. The Correct Way: Element-by-Element Copy
    3. Resizing an Array
  5. 2D Arrays
    1. Traversing a 2D Array
  6. ArrayList
  7. Stacks
  8. Queues
  9. Choosing the Right Structure
  10. Quick Check
  11. Trace Exercise
  12. Practice Exercises

Static vs Dynamic Structures

Every program needs to store collections of data. The question is how much flexibility you need.

Feature Static (Array) Dynamic (ArrayList, Stack, Queue)
Size Fixed at creation Grows or shrinks at runtime
Memory Allocated once Allocated as needed
Access Direct by index Depends on type
Speed Very fast Slight overhead

The key insight: static structures are simpler and faster when you know the size in advance. Dynamic structures are necessary when size changes at runtime — for example, adding items to a shopping cart or managing a print queue.


Picture it: Imagine a row of numbered mailboxes starting at 0. Each box holds exactly one item. The index is its position from the start — so box 0 is at the very beginning. How many boxes would you have if the last index is 4?

1D Arrays

An array stores a fixed number of values of the same type in contiguous memory. Each element is accessed by its index, starting at 0.

Declaring and Initialising

// Declare with a fixed size — all elements default to 0
int[] scores = new int[5];

// Declare and initialise with known values
int[] scores = {85, 72, 91, 60, 78};

// Access by index
System.out.println(scores[0]);   // 85
System.out.println(scores[4]);   // 78
scores[2] = 95;                  // modify an element

Array Length

System.out.println(scores.length);   // 5 — note: no parentheses, it's a property

Traversal

The standard pattern to visit every element:

for (int i = 0; i < scores.length; i++) {
    System.out.println("scores[" + i + "] = " + scores[i]);
}

Index i runs from 0 to scores.length - 1. Accessing scores[scores.length] causes an ArrayIndexOutOfBoundsException.


Common Array Operations

These operations appear frequently in exam questions and real programs. Each one is a fundamental algorithm — understanding the logic matters more than memorising the code.

Find Maximum and Minimum

int[] numbers = {34, 67, 12, 89, 45};

int max = numbers[0];   // assume first element is the largest
for (int i = 1; i < numbers.length; i++) {
    if (numbers[i] > max) {
        max = numbers[i];
    }
}
System.out.println("Maximum: " + max);  // 89

The same pattern applies for minimum — just flip > to <.

Sum and Average

int sum = 0;
for (int i = 0; i < numbers.length; i++) {
    sum = sum + numbers[i];
}
double average = (double) sum / numbers.length;
System.out.println("Sum: " + sum + ", Average: " + average);

Count Occurrences

int target = 45;
int count = 0;
for (int i = 0; i < numbers.length; i++) {
    if (numbers[i] == target) {
        count++;
    }
}
System.out.println(target + " appears " + count + " time(s).");

Duplicate Detection

Two common approaches, each answering a different question:

int[] numbers = new int[5];
// ... filled with values ...

// -------------------------------------------------------
// METHOD 1: Are ANY two elements the same?
// Compare every pair using nested loops
// -------------------------------------------------------
boolean duplicateFound = false;

for (int i = 0; i < numbers.length - 1 && !duplicateFound; i++) {
    for (int j = i + 1; j < numbers.length && !duplicateFound; j++) {
        if (numbers[i] == numbers[j]) {
            duplicateFound = true;
            System.out.println("Duplicate found: " + numbers[i]
                               + " at index " + i + " and index " + j);
        }
    }
}

// -------------------------------------------------------
// METHOD 2: Are ALL elements the same value?
// Compare every element against the first
// -------------------------------------------------------
boolean allSame = true;
int first = numbers[0];

for (int i = 1; i < numbers.length && allSame; i++) {
    if (numbers[i] != first) {
        allSame = false;
    }
}
System.out.println("All same: " + allSame);

Notice the && !duplicateFound condition in Method 1. This stops the inner loop as soon as a match is found — there is no point continuing. This is called an early exit and it is more efficient than always running to the end.


Try it first: Before reading this section, write int[] b = a;, then change b[0] = 99 and print a[0]. Does the result surprise you?

Copying Arrays

The Reference Trap

Arrays in Java are objects. When you assign one array variable to another, you are copying the reference (the address in memory), not the data.

int[] original = {1, 2, 3, 4, 5};
int[] copy = original;      // WRONG: both variables point to the same array

copy[0] = 99;
System.out.println(original[0]);   // 99 — original changed too!

In memory, both original and copy point to the same block of data. Modifying one modifies both.

The Correct Way: Element-by-Element Copy

int[] original = {1, 2, 3, 4, 5};
int[] copy = new int[original.length];   // allocate a new, separate array

for (int i = 0; i < original.length; i++) {
    copy[i] = original[i];              // copy each value individually
}

copy[0] = 99;
System.out.println(original[0]);   // 1 — original is untouched

Resizing an Array

Arrays have a fixed size. To “grow” an array, you must create a larger one and copy the data across:

int[] data = {10, 20, 30};      // original array, size 3

// Step 1: Create a larger temporary array
int[] temp = new int[data.length + 2];

// Step 2: Copy original elements into temp
for (int i = 0; i < data.length; i++) {
    temp[i] = data[i];
}

// Step 3: Reassign the reference
data = temp;

// Step 4: Null the temp variable (clean up the old reference)
temp = null;

System.out.println(data.length);   // 5

This four-step resize pattern is exactly how dynamic data structures (like ArrayList) work internally — they just do it automatically behind the scenes. Understanding it manually is the point.


2D Arrays

A 2D array is an array of arrays — a table with rows and columns.

// 3 rows, 4 columns — like a grid
int[][] grid = new int[3][4];

// Or initialise with values
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

// Access: matrix[row][column]
System.out.println(matrix[1][2]);   // 6 (row 1, column 2)

Traversing a 2D Array

// Print the entire matrix
for (int row = 0; row < matrix.length; row++) {
    for (int col = 0; col < matrix[row].length; col++) {
        System.out.print(matrix[row][col] + "\t");
    }
    System.out.println();
}

A 2D array is useful for: grade books (students × assignments), game boards (rows × columns), spreadsheet data.


ArrayList

An ArrayList is like an array that can grow and shrink. It stores objects (not primitives), and it handles resizing automatically.

import java.util.ArrayList;

ArrayList<String> names = new ArrayList<>();

// Add elements
names.add("Alice");
names.add("Bob");
names.add("Charlie");

// Access by index
System.out.println(names.get(0));       // Alice

// Size
System.out.println(names.size());       // 3  — note: .size(), not .length

// Remove by index
names.remove(1);                         // removes "Bob"
System.out.println(names);              // [Alice, Charlie]

// Check if contains
System.out.println(names.contains("Alice"));   // true

// Traverse
for (int i = 0; i < names.size(); i++) {
    System.out.println(names.get(i));
}
Operation Array ArrayList
Access arr[i] list.get(i)
Length/Size arr.length list.size()
Add Not possible list.add(value)
Remove Not possible list.remove(index)
Fixed size? Yes No

ArrayList stores objects only. For primitive types, Java uses wrapper classes: Integer for int, Double for double, Boolean for boolean. Java automatically converts between them (autoboxing).


Think about it: What does Ctrl+Z do? If you press it three times, what gets undone first — the first action or the most recent? What does that tell you about how the undo history must be stored?

Stacks

A stack is an abstract data structure that enforces a specific access rule: Last In, First Out (LIFO). Only the top element is accessible.

Think of a stack of plates — you add to the top and remove from the top.

Operation Meaning
push(value) Add an item to the top
pop() Remove and return the top item
peek() Look at the top item without removing it
isEmpty() Check if the stack is empty
import java.util.Stack;

Stack<Integer> stack = new Stack<>();

stack.push(10);
stack.push(20);
stack.push(30);

System.out.println(stack.peek());   // 30 — look at top
System.out.println(stack.pop());    // 30 — remove top
System.out.println(stack.pop());    // 20
System.out.println(stack.isEmpty()); // false — 10 still there

Why stacks matter: the call stack in your program is literally a stack — every time a method is called, a frame is pushed; when it returns, it is popped. Undo/redo in editors, browser back buttons, and expression evaluation all use stacks.

On IB exams, you may be asked to trace push/pop operations on a stack. Always keep track of the top pointer and draw the stack contents after each operation.


Think about it: When you send three documents to the printer, which one prints first? What would happen if the printer used a stack instead of a queue?

Queues

A queue enforces First In, First Out (FIFO) — the first item added is the first item removed. Think of a queue at a ticket counter.

Operation Meaning
enqueue(value) Add an item to the back
dequeue() Remove and return the front item
front() / peek() Look at the front item
isEmpty() Check if the queue is empty
import java.util.LinkedList;
import java.util.Queue;

Queue<String> queue = new LinkedList<>();

queue.add("Alice");     // enqueue
queue.add("Bob");
queue.add("Charlie");

System.out.println(queue.peek());    // Alice — look at front
System.out.println(queue.poll());    // Alice — remove front
System.out.println(queue.poll());    // Bob
System.out.println(queue.isEmpty()); // false — Charlie still waiting

Why queues matter: print queues, task schedulers, network packet buffers, and any system where order of arrival must be respected all use queues. The OS process scheduler you studied in the operating systems layer uses a queue.

LinkedList is one common Java implementation of a Queue. In IB exams, questions about queues are usually abstract (trace enqueue/dequeue operations) rather than code-specific.


Choosing the Right Structure

Situation Best choice
Fixed number of items, fast index access Array
Number of items changes at runtime ArrayList
Need LIFO (undo, backtracking) Stack
Need FIFO (order matters, job queue) Queue
Tabular data (grid, board, matrix) 2D Array

Quick Check

Q1. Given int[] arr = new int[6], what is the last valid index?

Q2. int[] b = a; b[0] = 99; — what is a[0]?

Q3. After push(10), push(20), push(30), pop() — what does peek() return?

Q4. Which data structure enforces FIFO (First In, First Out)?

Q5. Which declaration is valid for an ArrayList of integers?


Trace Exercise

Stack operations — fill in the top element and size after each operation.

Stack<Integer> s = new Stack<>();
s.push(5);
s.push(3);
s.push(8);
s.pop();
s.push(1);
s.pop();
OperationTop elementSize
push(5)
push(3)
push(8)
pop()
push(1)
pop()

What does s.peek() return after all operations?

What are the remaining stack contents, bottom to top?


Practice Exercises

  1. Write a program that fills an array of 10 integers with values entered by the user, then prints the minimum, maximum, and average.
  2. Write code in main that creates a reversed copy of {1, 2, 3, 4, 5}. Store the reversed elements in a new array without modifying the original, then print both arrays.
  3. Write code in main that counts how many elements in {34, 67, 12, 89, 45} are greater than 50. Print the result.
  4. Create a 3×3 array representing a tic-tac-toe board (using char). Write a loop to print it as a grid.
  5. Trace exercise — draw the contents of this stack after each line:
    Stack<Integer> s = new Stack<>();
    s.push(5);
    s.push(3);
    s.push(8);
    s.pop();
    s.push(1);
    s.pop();
    
  6. Challenge: Write a program that reads lines from the user until they enter “quit”. Store all lines in an ArrayList, then print them in reverse order.

Back to top

© EduCS.me — A resource hub for IB Computer Science

This site uses Just the Docs, a documentation theme for Jekyll.