Hierarchical Data Structures
CS205 Data Structures
Use arrow keys or buttons to navigate
A tree is a hierarchical data structure of nodes connected by edges.
One ancestor at the top, descendants branching down. Or a file system: root folder with subfolders and files.
n nodes → exactly n − 1 edges. There is exactly one path between any two nodes.
A tree T is either:
A tree with n nodes always has exactly n − 1 edges. Exactly one path between any two nodes (no cycles!).
Every node is the root of its own subtree. "Zoom in" on any node and you see a smaller tree. Click the buttons to see this in action!
| Method | Description |
|---|---|
root() | Return root node |
parent(v) | Return parent of v |
children(v) | Return children of v |
size() | Number of nodes |
depth(v) = edges from root to v.
Root has depth 0. Goes top-down ↓.
height(v) = edges on longest path from v down to a leaf.
Leaves have height 0. Goes bottom-up ↑.
height(T) = height of root = max depth of any leaf.
Here: height(A) = 3 (path A → B → D → F).
Each node has at most 2 children: a left and a right child.
| Property | Formula | Current |
|---|---|---|
| Max nodes at depth d | 2d | — |
| Max total nodes | 2h+1 − 1 | — |
| Min height (n nodes) | ⌊log₂ n⌋ | — |
| Actual height | — | — |
Binary trees enable efficient searching, sorting, and expression evaluation. The most common tree in CS.
A node with one child — it matters whether it's the left or right child. They are structurally different.
Every node has 0 or 2 children. No single-child nodes.
All levels full except last; last level filled left → right. Used in heaps!
All internals have 2 children; all leaves at same depth. Both full AND complete.
| Type | Rule | Relationship |
|---|---|---|
| Full | Every node: 0 or 2 children | Not necessarily complete |
| Complete | All levels full; last left-filled | Used in heaps! |
| Perfect | All leaves same depth, all internals have 2 | Both full AND complete |
Traversal = visiting every node exactly once. Choose the order based on your goal.
| Traversal | Order | Mnemonic | Use For |
|---|---|---|---|
| Preorder | Node, L, R | NLR | Copy/serialize |
| Inorder | L, Node, R | LNR | Sorted output (BST) |
| Postorder | L, R, Node | LRN | Delete / eval expr |
| Level-order | Top→bottom, L→R | BFS | Level-by-level |
The mnemonic tells you when you visit the node: before children (pre), between (in), or after (post).
Visit node FIRST, then recurse left, then recurse right.
Recurse left, visit node IN THE MIDDLE, then recurse right.
Inorder traversal of a BST visits nodes in ascending sorted order.
Recurse left, recurse right, visit node LAST.
Must finish all descendants before processing a node. Think: "clean up children before yourself."
Visit nodes level by level, left to right. Uses a queue.
The only standard traversal using a queue instead of recursion/stack.
For every node v:
| Op | BST (balanced) | Array | Linked List |
|---|---|---|---|
| Search | O(log n) | O(log n)* | O(n) |
| Insert | O(log n) | O(n) | O(1) |
| Delete | O(log n) | O(n) | O(n) |
* sorted array with binary search
At each node: go left (smaller) or right (larger). Like binary search on a sorted array, stored as a tree.
Compare target with current node. Go left if smaller, right if larger.
Like binary search on an array! Comparisons = depth of target node.
Search for the key. When you reach null, that's where the new node goes.
Insert never modifies existing nodes — just creates a new leaf at the correct position.
Inserting 1,2,3,4,5 in order creates a skewed tree (linked list!). Different orders → different shapes.
Just remove it
Replace with child
Find inorder successor
Delete 8: has two children, so find the inorder successor.
The smallest value larger than the deleted node. It always has at most one child (right only), so deleting it is Case 1 or 2.
Could also use the largest in the left subtree. Both work!
Given this tree, predict the output of each traversal.
Insert: 8, 4, 12, 2, 6, 10, 14
height = 2 ≈ log₂(7)
Insert: 2, 4, 6, 8, 10, 12, 14
height = 6 = n − 1 (linked list!)
| BST Type | Height | Operations |
|---|---|---|
| Balanced | O(log n) | O(log n) |
| Skewed | O(n) | O(n) |
Self-balancing trees (AVL, Red-Black) prevent this.
This BST insert function has a bug. Can you spot it?
Self-balancing trees guarantee O(log n) performance.
Balance Factor = height(left) − height(right) must be in {−1, 0, +1}. When violated → rotate.
Nodes are red or black. Rules ensure no path is more than 2× longer than any other.
Faster lookups, more rotations on insert/delete.
Fewer rotations, used by Java's TreeMap.
These will be covered in detail later. For now, know they exist and why: to prevent O(n) worst case.
For each scenario, choose the best data structure.
No ordering needed, just fast access.
Must support ordered iteration.
Nested elements with parent-child relationships.
Arithmetic with operator precedence.
Operators are internal nodes; operands are leaves. Evaluate with postorder!
| Traversal | Output | Notation |
|---|---|---|
| Preorder | × + 3 4 2 | Prefix (Polish) |
| Inorder | 3 + 4 × 2 | Infix (needs parens!) |
| Postorder | 3 4 + 2 × | Postfix (RPN) |
| Name | Order | Use For |
|---|---|---|
| Preorder | NLR | Copy/serialize |
| Inorder | LNR | Sorted output (BST) |
| Postorder | LRN | Delete / eval expr |
| Level-order | BFS | Level-by-level |
| Type | Height | Ops |
|---|---|---|
| Balanced | O(log n) | O(log n) |
| Skewed | O(n) | O(n) |
Trees organize data hierarchically. BSTs give O(log n) search/insert/delete — but only when balanced.
A perfect binary tree of height 3 has how many nodes?
Which traversal gives sorted output from a BST?
Deleting a node with two children requires finding the:
Insert these keys in order: 5, 3, 8, 1, 4, 7, 9. What is the tree's height?
Called on this BST: