Chapter 1: Introduction to Data Structures and Algorithms
1.03Beginner10 topics14 min3 interactive animations

Core vocabulary

The shared vocabulary of DSA: elements and indexes, keys and values, nodes and edges, references, state, invariants, mutability, ordering and stability. Every later chapter assumes these ten words.

Learning goals

  • Use the core terms precisely
  • Explain what a reference is and how aliasing causes surprises
  • Tell ordered from sorted, and stable from unstable
  • Recognise an invariant

Prerequisites

Arrays and variables
1.03.1

Element

An element is one item stored in a collection: in int[] a = {4, 9, 2}, the values 4, 9 and 2 are elements. “Size” or “length” is the number of elements.

1.03.2

Index

An index is an element's position. Java arrays and lists are zero-based: the first element is at index 0 and the last at length - 1. Reading outside that range throws ArrayIndexOutOfBoundsException or IndexOutOfBoundsException.

Off-by-one errors, from mixing up < with <= or the last valid index with the length, are the most common bug in this whole subject.

1.03.3

Key and value

A key identifies an entry; a value is the data attached to it. In a map from student ID to name, the ID is the key and the name is the value. Keys are looked up and compared; values are carried along.

In sorting and searching the key is the field used for comparison, even when the whole record travels with it.

Java
1Map<Integer, String> names = new HashMap<>();
2names.put(1042, "Ana"); // key 1042, value "Ana"
3String who = names.get(1042); // look up by key
1.03.4

Node and edge

A node (or vertex) stores data. An edge is a connection from one node to another. Linked lists, trees and graphs are all built from nodes and edges and differ only in which connections are allowed.

A linked list node has one outgoing edge (next), a binary tree node has up to two (left, right), and a graph node may have any number.

Java
1class Node {
2 int value;
3 Node next; // one edge: this is a linked list node
4 Node(int value) { this.value = value; }
5}
1.03.5

Pointer and reference

Java has no raw pointers. A variable of object type holds a reference: the address of an object on the heap, not the object itself. Copying a reference creates a second name for the same object (an alias), so a change through either name is visible through both.

Primitives (int, double, …) are copied by value. Arrays and objects are shared by reference. Step through the animation to see exactly when two variables share one object and when they do not.

Aliasing and copying arrays

Interactive · edit the input

Your input

Try

variables

a → @1

@1 int[]

100
201
302
403
Setup

new int[] creates one object on the heap; the variable a holds only a reference to it.

Step 1 / 4
Java
1int[] a = { 10, 20, 30, 40 }; // options 0 and 1 use this 1D array
2int[] b = a; // option 0: copies the reference only
3int[] b = a.clone(); // option 1: copies the elements
4int[][] a2 = { { 10, 20 }, { 30, 40 } }; // options 2 and 3 use this 2D array
5int[][] b2 = a2.clone(); // option 2: new outer array, SAME row objects
6int[][] b2 = Arrays.stream(a2).map(int[]::clone).toArray(int[][]::new); // option 3: rows copied too
7b[idx] = v; // (b2[0][idx] = v for options 2 and 3)
8System.out.println(Arrays.toString(a)); // does a see the change?

Live state

0 writes

a.length

4

No condition evaluated on this step
Execution trace (dry run table)Show 4 steps
StepLineStateWhat happens
1L1a.length=4new int[] creates one object on the heap; the variable a holds only a reference to it.
2L2same=trueb = a copies the reference, not the array. Both variables now point at the same object (@1).
3L7idx=1 v=99b[1] = 99 writes into the object b points at.
4L8a=[10, 99, 30, 40] b=[10, 99, 30, 40]a shows the change too ([10, 99, 30, 40]), because a and b are two names for one object.
1.03.6

State

State is the current value of every variable that can affect what happens next. An algorithm is a sequence of state changes. Describing the state precisely after each step is what a tracing table does.

Smaller state is easier to reason about. Prefer algorithms that carry a few well-named variables over ones that depend on many interacting flags.

1.03.7

Invariant

An invariant is a condition that stays true across a repeated step, typically at the top of each loop iteration. It is the main tool for proving an algorithm correct. In linear search, “the target is not in arr[0..i-1]” holds before every iteration.

Chapter 7 (the State and Invariants lesson) turns this into a method with worked examples, including Kadane's algorithm.

1.03.8

Mutable and immutable

A mutable object can change after creation (ArrayList, arrays, StringBuilder). An immutable object cannot (String, Integer, records with final fields). Immutable objects are safe to share and to use as map keys; mutable ones need care.

Mutating an object that is already a key in a HashMap or HashSet changes its hash code and makes it unfindable. Always use immutable types as keys.

Java
1String s = "cat";
2String t = s.concat("s"); // new object; s is still "cat"
3
4StringBuilder sb = new StringBuilder("cat");
5sb.append('s'); // same object changed in place
1.03.9

Ordered and unordered

Ordered means the collection remembers an order: insertion order (ArrayList, LinkedHashSet) or sorted order (TreeSet). Unordered means there is no promised order (HashSet, HashMap). Ordered is not the same as sorted: a list is ordered by position even if its values are random.

The animation adds the same values to five collections. Compare how each one stores them: only TreeSet is sorted, and the HashSet order is an implementation detail.

Same values, different collections

Interactive · edit the input

Your input

Try

ArrayList

empty

LinkedHashSet

empty

HashSet (capacity 16)

empty

TreeSet

empty

PriorityQueue array

empty
Setup

Five collections receive exactly the same values in the same order. Watch how each one stores them.

Step 1 / 10
Java
1List<Integer> list = new ArrayList<>();
2Set<Integer> linked = new LinkedHashSet<>();
3Set<Integer> hash = new HashSet<>();
4Set<Integer> tree = new TreeSet<>();
5PriorityQueue<Integer> heap = new PriorityQueue<>();
6for (int x : arr) {
7 list.add(x); // keeps insertion order, keeps duplicates
8 linked.add(x); // keeps insertion order, drops duplicates
9 hash.add(x); // order decided by hash buckets
10 tree.add(x); // always sorted
11 heap.add(x); // heap array: only the smallest is guaranteed first
12}
13System.out.println(list + " " + linked + " " + hash + " " + tree + " " + heap);

Live state

values

8

No condition evaluated on this step
Execution trace (dry run table)Show 10 steps
StepLineStateWhat happens
1L1values=8Five collections receive exactly the same values in the same order. Watch how each one stores them.
2L7x=42 adds so far=1 distinct=1 HashSet capacity=1642 goes to bucket 10 of 16 in the HashSet (index = (h ^ (h >>> 16)) & 15).
3L7x=7 adds so far=2 distinct=2 HashSet capacity=167 goes to bucket 7 of 16 in the HashSet (index = (h ^ (h >>> 16)) & 15).
4L7x=19 adds so far=3 distinct=3 HashSet capacity=1619 goes to bucket 3 of 16 in the HashSet (index = (h ^ (h >>> 16)) & 15).
5L7x=7 adds so far=4 distinct=3 HashSet capacity=167 is already present: the ArrayList and the PriorityQueue keep a second copy, the three sets ignore it.
6L7x=3 adds so far=5 distinct=4 HashSet capacity=163 goes to bucket 3 of 16 in the HashSet (index = (h ^ (h >>> 16)) & 15).
7L7x=25 adds so far=6 distinct=5 HashSet capacity=1625 goes to bucket 9 of 16 in the HashSet (index = (h ^ (h >>> 16)) & 15).
8L7x=16 adds so far=7 distinct=6 HashSet capacity=1616 goes to bucket 0 of 16 in the HashSet (index = (h ^ (h >>> 16)) & 15).
9L7x=33 adds so far=8 distinct=7 HashSet capacity=1633 goes to bucket 1 of 16 in the HashSet (index = (h ^ (h >>> 16)) & 15).
10L13distinct=7 capacity=16Same values, five different orders. Only the TreeSet is sorted; the HashSet order is an implementation detail you must never depend on, and the PriorityQueue promises only that index 0 is the minimum.
1.03.10

Stable vs unstable

A sort is stable if elements with equal keys keep their original relative order. Stability matters when you sort by one key and then another, such as by department and then by salary.

Merge sort, insertion sort and Java's object sort are stable. Quick sort, selection sort and heap sort are not. The demo shows equal values tagged a, b, c and what each algorithm does to their order.

Stability: what happens to equal keys?

Interactive

Your input

Try

Input · letters show original order of equal keys

3a3b2a2b2c1

Insertion sort

12a2b2c3a3b
a before b

Bubble sort

12a2b2c3a3b
a before b

Selection sort

12a2b2c3b3a
Order broken

Shell sort

12b2c2a3a3b
Order broken

Practice ladder

Now try it yourself

Easy

  • Explain the difference between ordered and sorted with an example
  • What does int[] b = a; do, and what does int[] b = a.clone(); do?

Medium

  • Why is a mutable object a dangerous HashMap key? Show a failing example
  • State an invariant for finding the minimum of an array

Advanced

  • Give an input where an unstable sort produces a different result than a stable one in a two-key sort

Key takeaways

  • Elements live at indexes; keys identify values; nodes connect through edges.
  • Object variables hold references, so assignment aliases instead of copying.
  • Invariants prove loops correct; stability and mutability decide which tools are safe.