Chapter 15: Data Structure Selection and Implementation Trade-offs
15.01Beginner / Intermediate7 topics16 min1 interactive animation

Operation matrices

Operation-by-operation cost tables for arrays, sorted arrays, linked lists, deques, hash tables, balanced trees and heaps: index access, insert, delete, search, min/max, predecessor/successor and range queries.

Learning goals

  • Read the cost of each operation for the common structures
  • Match a problem's dominant operations to the structure that makes them cheap
  • Recognise which operations a structure does not support at all

Prerequisites

Arrays and dynamic arraysLinked listsHash tables, maps and setsPriority queues

Choosing a data structure is choosing which operations to make cheap. A phone book is fast to search by name and hopeless for finding everyone whose number ends in 7: the structure decides.

15.01.1

Index access

Index access means “give me the k-th element”. Arrays and ArrayList compute the address from the index in O(1). A linked list must walk k nodes. Hash maps and trees have no positions at all: they are addressed by key, and TreeMap cannot even report the k-th smallest key without walking.

Run the animation to see the difference between reading element 5 of an array and of a linked list.

StructureGet by positionGet by key
Array / ArrayListO(1)-
Sorted arrayO(1)O(log n) binary search
LinkedListO(n)-
ArrayDequeNot supported-
HashMap / HashSet-O(1) expected
TreeMap / TreeSetNot supported (O(n) by iterating)O(log n)
PriorityQueueOnly the root: peek() is O(1)-

Reading element k: array vs linked list

Interactive · edit the input

Your input

Try

array memory (value, address)

12@1000
7@1004
31@1008
4@1012
19@1016
8@1020
25@1024
Setup

The 7 values sit in consecutive memory cells, 4 bytes apart, starting at address 1000.

Step 1 / 3
Java
1static int getFromArray(int[] arr, int k) {
2 return arr[k]; // address = base + k * 4: one memory read
3}
4
5static int getFromList(Node head, int k) {
6 Node cur = head;
7 for (int i = 0; i < k; i++) {
8 cur = cur.next; // pointer chase: one read per hop
9 }
10 return cur.value;
11}

Live state

0 memory reads

k

5

base

1000

No condition evaluated on this step
Execution trace (dry run table)Show 3 steps
StepLineStateWhat happens
1L1k=5 base=1000The 7 values sit in consecutive memory cells, 4 bytes apart, starting at address 1000.
2L2k=5 address=1020Address = 1000 + 5 × 4 = 1020. One multiplication and one addition give the location, no matter how large k is.
3L2return=8return 8 with a single memory read: O(1) random access.
15.01.2

Insert

Inserting at the end of an array list is amortised O(1); inserting anywhere else shifts the tail, O(n). A linked list inserts in O(1) once it holds the node, but *finding* the position costs O(n). Hash tables insert in expected O(1), balanced trees and heaps in O(log n).

A sorted array is the worst for insertion: O(log n) to find the spot, then O(n) to shift. That is the price of its O(1) minimum and O(log n) search.

StructureInsert
ArrayListEnd: O(1) amortised; middle: O(n)
Sorted arrayO(n): binary search O(log n) plus shifting
LinkedListEnds: O(1); at index: O(n) to walk, O(1) to link
ArrayDequeEnds: O(1) amortised; middle: not supported
HashMap / HashSetO(1) expected
TreeMap / TreeSetO(log n)
PriorityQueueoffer: O(log n)
15.01.3

Delete

Deletion mirrors insertion. Removing the last element of an array list is O(1); removing from the front or the middle shifts the tail. Linked lists unlink in O(1) at either end of a doubly linked list. PriorityQueue.poll() removes the best element in O(log n), but remove(Object) must first search the heap, O(n).

StructureDelete
ArrayListEnd: O(1); front or middle: O(n)
Sorted arrayO(n) (shifting)
LinkedListEnds: O(1); by value or index: O(n) to find
ArrayDequeEnds: O(1); removeFirstOccurrence: O(n)
HashMap / HashSetO(1) expected
TreeMap / TreeSetO(log n)
PriorityQueuepoll: O(log n); remove(Object): O(n)
15.01.5

Min/max

The minimum and maximum are free in a sorted array (the two ends), cheap in a balanced tree (the leftmost and rightmost nodes, O(log n)) and, for one of them, free in a heap (the root). A hash table keeps no order, so it scans.

A heap gives only one extreme: a min-queue has the minimum at the root and finding the maximum means scanning. If you need both, use a TreeMap/TreeSet, or two heaps.

StructureMinimumMaximum
Unsorted array / list / dequeO(n)O(n)
Sorted arrayO(1)O(1)
HashMap / HashSetO(n)O(n)
TreeMap / TreeSetO(log n)O(log n)
PriorityQueue (min-heap)O(1)O(n)
15.01.6

Predecessor/successor

The predecessor of x is the largest value below x; the successor is the smallest above it. They answer questions such as “which meeting starts right after 14:00?”. A sorted array finds them with binary search in O(log n); TreeSet.lower/higher/floor/ceiling do it in O(log n) in a tree. Hash tables and heaps cannot answer these without scanning everything.

StructurePredecessor / successor
Unsorted array / list / dequeO(n)
Sorted arrayO(log n)
HashMap / HashSetO(n)
TreeMap / TreeSetO(log n): lowerKey, higherKey, floorKey, ceilingKey
PriorityQueueNot supported (O(n) by scanning)
Java
1static void neighbours() {
2 TreeSet<Integer> starts = new TreeSet<>(List.of(900, 1030, 1400, 1530));
3 System.out.println(starts.lower(1400) + " " + starts.higher(1400) + " " + starts.ceiling(1401)); // 1030 1530 1530
4}
15.01.7

Range query

A range query returns everything with a key between lo and hi. Sorted structures locate the start in O(log n) and then walk the k results: O(log n + k). Unsorted structures must test every element, O(n), even when few match.

StructureAll keys in [lo, hi]
Unsorted array / list / dequeO(n)
Sorted arrayO(log n + k)
HashMap / HashSetO(n)
TreeMap / TreeSetO(log n + k) with subMap / subSet
PriorityQueueO(n)
Java
1static List<Integer> inRange(TreeSet<Integer> set, int lo, int hi) {
2 return new ArrayList<>(set.subSet(lo, true, hi, true)); // finds lo in O(log n), then walks the results
3}

Practice ladder

Now try it yourself

Easy

  • Which structure gives O(1) minimum and O(log n) search?
  • Why can ArrayDeque not return the k-th element?

Medium

  • Design a data structure with insert, delete and getRandom in O(1)
  • My Calendar I (use TreeMap)

Advanced

  • Design a structure that supports insert, delete and k-th smallest in O(log n)

Key takeaways

  • Every structure makes some operations cheap and others impossible or O(n).
  • Order-based questions (min, max, predecessor, range) need a sorted structure; exact lookups favour hashing.
  • Write down the dominant operations of a problem first, then read the matching column.