Foundational Data Structures~20 min

Choosing a Structure

Every structure in this module answers a different question well — picking the wrong one doesn't just cost speed, it forces awkward workarounds.

By the end of this lesson, you can

  • Apply a small set of questions to choose the right structure for a scenario
  • Compare lists, dictionaries, sets, stacks, queues, trees, and graphs side by side
  • Explain why forcing a familiar structure onto the wrong problem leads to awkward, unnecessary code

Why it matters

Every structure in this module models information differently, and picking the wrong one for a problem doesn’t just cost some speed — it usually forces genuinely awkward code, working around a mismatch that a different structure wouldn’t have had at all.

Mental model

Four questions, asked in order, point toward the right structure:

  1. Is order meaningful, or is the data just a collection?
  2. How will items be found — by position, by a meaningful key, or just “is this present at all”?
  3. Must duplicates be allowed, or does every value need to be unique?
  4. Which end (or point) does work happen at — the most recent item, the oldest, a hierarchy, or an arbitrary network of connections?
Every structure from this module, side by side
StructureFound byOrderDuplicates?Best for
ListPosition (index)Preserves insertion orderAllowedAn ordered collection, accessed by position
DictionaryKeyPreserves insertion order, but accessed by keyKeys unique, values can repeatLooking something up by a meaningful key
SetMembership onlyNo meaningful orderNever — automatically collapsedFast uniqueness or membership checks
StackMost recently addedLast-in-first-outAllowedUndo history, nested structure
QueueEarliest addedFirst-in-first-outAllowedProcessing items in arrival order
TreeParent/child referencesHierarchical, no cyclesA hierarchy with one root
GraphArbitrary referencesAny pattern, cycles allowedA network of connections

Small example

PythonForcing a list to do a dictionary's job
prices = [("milk", 3.50), ("eggs", 2.80), ("bread", 4.00)]

def find_price(prices, item):
    for name, price in prices:
        if name == item:
            return price
    return None

print(find_price(prices, "eggs"))
Output
2.8

This works — but it’s a dictionary problem wearing a list’s clothes. find_price has to check every entry one at a time, and every place that needs a price has to remember to call this helper function instead of writing prices["eggs"] directly.

PythonThe structure that actually fits
prices = {"milk": 3.50, "eggs": 2.80, "bread": 4.00}
print(prices["eggs"])
Output
2.8

Same answer, no helper function needed, and it stays fast as the number of products grows — because a dictionary is what this problem actually is.

Check your understanding

You need to process customer support tickets in the exact order they arrived. Which structure fits?
Or reveal the answer without checking

Answer:A queue
Processing in arrival order is exactly what a queue models — first in, first out — with no need for keys, hierarchy, or uniqueness.

Why is 'the structure I already know how to use' a risky reason to choose one?
Or reveal the answer without checking

Answer:A structure that doesn't fit the problem often still "works," at the cost of awkward workarounds and code that only gets slower and harder to follow as the data grows
A mismatched structure rarely fails outright — it just quietly costs more code, more edge cases, and worse growth behavior than the structure that actually fit the problem.

Practice: warm-up

For each scenario, name the structure that fits best: (1) checking whether an email has already registered, (2) a browser’s back-button history, (3) a family tree, (4) a road map between cities, (5) looking up a student’s grade by their ID.

Stuck? Reveal one hint at a time.

  1. Hint 1

    Ask the four questions for each: order matters? found by position, key, or membership? duplicates allowed? which end does work happen at?

  2. Hint 2

    A road map and a family tree look similar at a glance — but one has a single root and no cycles, and the other doesn't.

Reveal one reasonable set of answers

Try the problem yourself before reading this. There is often more than one reasonable approach — treat this as one worked example, not the only correct answer.

1. Already registered?        -> set (pure membership check)
2. Back-button history        -> stack (most recent page first)
3. Family tree                -> tree (one root, hierarchy, no cycles)
4. Road map between cities    -> graph (any connection pattern, cycles allowed)
5. Grade by student ID        -> dictionary (lookup by a meaningful key)

Practice: apply it

This code checks whether a username has already been taken, using a list and a manual search every time:

taken_usernames = ["ada99", "grace_h", "linus_t"]

def is_taken(usernames, name):
    for existing in usernames:
        if existing == name:
            return True
    return False

print(is_taken(taken_usernames, "grace_h"))
As taken_usernames grows to contain millions of names, what happens to is_taken?
Or reveal the answer without checking

Answer:It gets slower, checking names one by one — exactly the problem a set solves, since this is a pure membership question with no order or position involved
This is a membership question through and through — no order, no position, no keys. A set answers it directly and stays fast regardless of size, while the list-based version gets slower as it grows.

Modification challenge: rewrite taken_usernames as a set and replace is_taken with a direct name in taken_usernames check.

Summary

  • Ask what’s meaningful about the data — order, lookup method, uniqueness, and which end work happens at — before choosing a structure.
  • Every structure in this module answers a different combination of those questions well; none of them is a universal default.
  • A structure that doesn’t fit a problem can usually still be made to work, at the cost of awkward, slower code that only gets worse as the data grows.
  • When code feels like it’s fighting its own data structure — manual searches, hand-checked duplicates — that’s a sign worth reconsidering the choice, not just optimizing the workaround.