A dictionary (also called a map) stores key–value pairs and supports three core operations:
dictBy the end of today's class, you will be able to:
h = height of the tree (we'll define this precisely soon)
Invariant = a condition that must remain true before and after every operation.
17 is the right child of 10 — and 17 > 10, so locally it looks correct.
But 17 is in the left subtree of 15, so it must be < 15. It's not!
Key idea: at each node, the invariant tells us which side to explore. We never check both.
| Step | At node | Compare | Go |
|---|---|---|---|
| 1 | 8 | 7 < 8 | Left |
| 2 | 3 | 7 > 3 | Right |
| 3 | 6 | 7 > 6 | Right |
| 4 | 7 | 7 == 7 | Found! |
What happens when the key isn't in the tree? We walk until we reach None.
Search for 9 on the standard tree (8, 3, 12, 1, 6, 14).
| Step | At node | Compare | Go |
|---|---|---|---|
| 1 | 8 | 9 > 8 | Right |
| 2 | 12 | 9 < 12 | Left |
| 3 | None | — | Not found! |
None → return False.
| Step | At node | Compare | Go |
|---|---|---|---|
| 1 | 8 | 13 > 8 | Right |
| 2 | 12 | 13 > 12 | Right |
| 3 | 15 | 13 < 15 | Left |
| 4 | 13 | 13 == 13 | Found! |
Insertion = search until you fall off, then attach a new leaf there.
| Step | At node | Compare | Go |
|---|---|---|---|
| 1 | 8 | 5 < 8 | Left |
| 2 | 3 | 5 > 3 | Right |
| 3 | 6 | 5 < 6 | Left |
| 4 | null | — | Create node(5) |
| Insert 9 | |||
|---|---|---|---|
| 1 | 8 | 9 > 8 | Right |
| 2 | 12 | 9 < 12 | Left |
| 3 | 10 | 9 < 10 | Left |
| 4 | None | — | Attach left of 10 |
| Insert 2 | |||
| 1 | 8 | 2 < 8 | Left |
| 2 | 3 | 2 < 3 | Left |
| 3 | 1 | 2 > 1 | Right |
| 4 | None | — | Attach right of 1 |
The same keys inserted in a different order produce different trees with different heights.
No children → just remove it.
Replace node with its only child.
Find in-order successor, copy key up, delete successor.
find_min(node.right).Right subtree of 8, then keep going left.
Every operation follows one root-to-leaf path. Work is proportional to height h.
| Operation | Runtime | Why? |
|---|---|---|
| search(key) | O(h) | Follow one path down |
| insert(key) | O(h) | Search + attach leaf |
| delete(key) | O(h) | Find + restructure |
| findMin / findMax | O(h) | Walk one side |
| in-order traversal | O(n) | Visit every node |
How does a BST stack up against other ways to implement a dictionary?
| Structure | Search | Insert | Delete | Sorted Output |
|---|---|---|---|---|
| Unsorted Array / List | O(n) | O(1) | O(n) | O(n log n) |
| Sorted Array | O(log n) | O(n) | O(n) | O(n) |
| Hash Table | O(1) avg | O(1) avg | O(1) avg | O(n log n) |
| BST (balanced) | O(log n) | O(log n) | O(log n) | O(n) |
Next class: Balanced BSTs — structures that enforce O(log n) height.