Skip to content
AI-grafen
DAI developerComputer science· about 45 min· fundamentals that rarely change· verified 2026-09-20· EN

Data structures: lists, stacks, queues, hash tables

Be able to choose the right data structure and explain why a dictionary lookup is fast.

Prerequisites

Intuition

A data structure is a way of laying things out so that exactly the operations you need are fast. There is none that is best at everything.

StructureFastSlowPicture
Listindexing, appending at the endsearching, removing in the middlea bookshelf in order
Stackputting on and taking off the topeverything elsea stack of plates (last in, first out)
Queueadding at the end, taking from the fronteverything elsea checkout queue (first in, first out)
Hash table (dict)looking up by keyorder, rangesa phone book that looks up directly
Setmembershiporder«is this one in there?»

The most important insight: searching a list of a million elements takes a million comparisons. Looking up in a dictionary of a million keys takes roughly one. The difference is not «a bit faster» — it is the whole difference between the code being runnable and not.

Formal

The complexity of the common operations:

OperationListDict / SetDeque
Index x[i]O(1)—O(1) at the ends
Search v in xO(n)O(1)O(n)
Append at the endO(1)*O(1)O(1)
Add/remove at the frontO(n)—O(1)
Remove in the middleO(n)O(1)O(n)

* amortised: the list is occasionally regrown, but the cost is spread out.

How a hash table works. A hash function turns the key into a number, and the number points out a slot in an array. Looking up therefore becomes «compute the number, go straight there» — independently of how many elements there are.

Two keys can land in the same slot (a collision). That is solved with chains or with reprobing, and that is why O(1) is an average, not a guarantee. In the worst case it becomes O(n), but with a good hash function that practically never happens.

The price: the keys have to be hashable, that is, immutable. That is why a list cannot be a key in a dict — but a tuple can.

The most common performance error in Python code is searching a list inside a loop:

for x in the_big_list:          # n times
    if x in other_list:         # n comparisons each time  → O(n²)

One line is enough to fix it: other_set = set(other_list) before the loop. With n = 10 000 it goes from about 50 million comparisons to 10 000.

Code

import time
from collections import deque, Counter, defaultdict

n = 200_000
items = list(range(n))
item_set = set(items)

def ms(f):
    t = time.perf_counter(); f(); return (time.perf_counter() - t) * 1000

print(f"list: {ms(lambda: [n - 1 in items for _ in range(100)]):.1f} ms")
print(f"set:  {ms(lambda: [n - 1 in item_set for _ in range(100)]):.1f} ms")
# list: 210.4 ms
# set:    0.0 ms      ← the same question, ~10 000 times faster

# A stack: last in, first out
stack = []
stack.append("a"); stack.append("b")
print(stack.pop())                      # b

# A queue: use a deque, not a list — list.pop(0) is O(n)
queue = deque(["a", "b"])
queue.append("c")
print(queue.popleft())                  # a

# Two dict tools that save a lot of code
words = "one two one three two one".split()
print(Counter(words).most_common(2))    # [('one', 3), ('two', 2)]

groups = defaultdict(list)
for name, form in [("Ada", "7A"), ("Bo", "7B"), ("Cim", "7A")]:
    groups[form].append(name)
print(dict(groups))                     # {'7A': ['Ada', 'Cim'], '7B': ['Bo']}

# The keys have to be hashable
d = {("row", 1): "value"}               # a tuple is fine
try:
    d[["row", 1]] = "value"             # a list is not
except TypeError as e:
    print(e)                            # unhashable type: 'list'

Mastery means

  • Chooses the data structure according to the operation
  • Explains how a hash table works
  • Recognises when the wrong structure makes the code slow

Sign in to do the exercises and build your mastery up.

Sources

All the sources and licences