Skip to content
Part IA Lent Term

The Dictionary Problem

The Dictionary ADT

A dictionary (also called a map or associative array) stores a set of (key, value) pairs and supports three core operations:

  • INSERT(key, value): add a new pair, or update the value if key already exists.
  • DELETE(key): remove the pair with the given key.
  • SEARCH(key): return the value associated with the key, or indicate absence.

The dictionary is one of the most fundamental abstract data types in computing. It underpins symbol tables in compilers, routing tables in networks, caches in operating systems, and database indices.

Naive Implementations

Unsorted Array

Keep pairs in an array in any order.

  • INSERT: append to end, O(1)O(1).
  • SEARCH: linear scan, O(n)O(n).
  • DELETE: find then remove (or mark as deleted), O(n)O(n).

Sorted Array

Keep pairs sorted by key. SEARCH uses binary search: O(logn)O(\log n). But INSERT requires shifting elements to maintain sorted order: O(n)O(n). DELETE also O(n)O(n).

Balanced BST (e.g. Red-Black Tree)

All three operations in O(logn)O(\log n). This is the best worst-case guarantee among comparison-based structures.

The Hash Table Promise

Hash tables aim for O(1)O(1) expected time for all three operations. The core idea: compute an array index directly from the key using a hash function, then store the pair at that position.

Given key "Cambridge", compute h("Cambridge") = 3, and store the value at table slot T[3]. Future searches for "Cambridge" go directly to slot 3 without comparing against other keys (unless there is a collision).

The Inevitability of Collisions

By the pigeonhole principle: the number of possible keys vastly exceeds the number of table slots. Even for integer keys: if UUIDs (128-bit) are keys and the table has 10610^6 slots, 21282^{128} keys map into 10610^6 slots; many keys must share the same index.

A collision occurs when two distinct keys k1k2k_1 \neq k_2 produce the same hash value: h(k1)=h(k2)h(k_1) = h(k_2). Collision resolution is the central design challenge of hash tables.

Key Design Decisions

Building an effective hash table requires choosing:

  1. Hash function: maps keys to table indices. Must be fast to compute and produce a uniform distribution across the table.
  2. Collision resolution strategy: what to do when two keys map to the same slot. Two main families: chaining (linked lists per slot) and open addressing (probing for an empty slot).
  3. Load factor management: when to grow (or shrink) the table to maintain performance.

Example: Collision in Practice

Hash function h(k)=kmod10h(k) = k \bmod 10, table size m=10m = 10.

INSERT(23, "Alice"):  h(23) = 3  → T[3] = ("Alice")
INSERT(47, "Bob"):    h(47) = 7  → T[7] = ("Bob")
INSERT(13, "Carol"):  h(13) = 3  → COLLISION with Alice!

The hash table must now resolve what happens at slot 3. With chaining, both entries live in a linked list at T[3]. With open addressing, Carol probes for the next empty slot.

Summary

ImplementationINSERTSEARCHDELETE
Unsorted arrayO(1)O(1)O(n)O(n)O(n)O(n)
Sorted arrayO(n)O(n)O(logn)O(\log n)O(n)O(n)
Balanced BSTO(logn)O(\log n)O(logn)O(\log n)O(logn)O(\log n)
Hash table (expected)O(1)O(1)O(1)O(1)O(1)O(1)
CollisionTwo keys map to same slot
Load factor α\alphaα=n/m\alpha = n/m, nn keys, mm slots