Binary Search Trees
IB Syllabus: B4.1.4 (HL) – Explain the structures and properties of BSTs: data organization, insert, delete, search, traverse; sketching as tree diagram. (Delete is covered in BST Operations.)
This page is HL only.
Table of Contents
- Key Concepts
- Worked Examples
- Quick Code Check
- Trace Exercise
- Code Completion
- Spot the Bug
- Output Prediction
- Practice Exercises
- Connections
Key Concepts
A Binary Search Tree (BST) is a hierarchical data structure where each node has at most two children (left and right), and the data is organized so that searching, inserting, and retrieving in sorted order are efficient.
The BST Property
For every node in the tree:
- All values in the left subtree are less than the node’s value
- All values in the right subtree are greater than the node’s value
This rule applies recursively to every subtree.
Tree Terminology
| Term | Meaning |
|---|---|
| Root | The topmost node (no parent) |
| Parent | A node that has one or two children below it |
| Left child | The child with a smaller value |
| Right child | The child with a larger value |
| Leaf | A node with no children (both left and right are null) |
| Internal node | A node that has at least one child |
| Subtree | A node and all its descendants |
| Height | Number of levels from root to the deepest leaf |
The TreeNode Class
public class TreeNode {
int data;
TreeNode left;
TreeNode right;
public TreeNode(int data) {
this.data = data;
this.left = null;
this.right = null;
}
}
Each node stores data and two references – one to its left child and one to its right child. Like linked list nodes, tree nodes are self-referential.
Why BSTs?
| Structure | Search | Insert | Sorted output |
|---|---|---|---|
| Unsorted array | O(n) | O(1) | O(n log n) sort needed |
| Sorted array | O(log n) binary search | O(n) shift elements | Already sorted |
| Linked list | O(n) | O(1) at head | O(n log n) sort needed |
| BST (balanced) | O(log n) | O(log n) | O(n) in-order traversal |
A balanced BST gives O(log n) search AND O(log n) insert – the best of both worlds. In-order traversal produces sorted output without needing a separate sorting step.
Worked Examples
Example 1: BST Insert and In-Order Traversal
public class BST {
private TreeNode root;
public BST() {
root = null;
}
// Insert a value into the BST
public void insert(int value) {
root = insertRec(root, value);
}
private TreeNode insertRec(TreeNode node, int value) {
if (node == null) {
return new TreeNode(value); // found the spot
}
if (value < node.data) {
node.left = insertRec(node.left, value);
} else if (value > node.data) {
node.right = insertRec(node.right, value);
}
// duplicate values are ignored
return node;
}
// In-order traversal: Left, Node, Right (produces sorted output)
public void inOrder() {
inOrderRec(root);
System.out.println();
}
private void inOrderRec(TreeNode node) {
if (node == null) {
return;
}
inOrderRec(node.left);
System.out.print(node.data + " ");
inOrderRec(node.right);
}
public static void main(String[] args) {
BST tree = new BST();
tree.insert(45);
tree.insert(25);
tree.insert(65);
tree.insert(15);
tree.insert(30);
tree.insert(55);
tree.insert(75);
System.out.println("In-order traversal:");
tree.inOrder();
}
}
Output:
In-order traversal:
15 25 30 45 55 65 75
The values were inserted in the order 45, 25, 65, 15, 30, 55, 75 but the in-order traversal outputs them sorted. This is the key power of a BST: in-order traversal always produces sorted output.
How insertion builds the tree:
Insert 45: 45 (root)
Insert 25: 45
/
25
Insert 65: 45
/ \
25 65
Insert 15: 45
/ \
25 65
/
15
Insert 30: 45
/ \
25 65
/ \
15 30
Insert 55: 45
/ \
25 65
/ \ /
15 30 55
Insert 75: 45
/ \
25 65
/ \ / \
15 30 55 75
Example 2: Search
// Search for a value in the BST
public boolean contains(int target) {
return containsRec(root, target);
}
private boolean containsRec(TreeNode node, int target) {
if (node == null) {
return false; // reached a leaf -- not found
}
if (target == node.data) {
return true; // found it
}
if (target < node.data) {
return containsRec(node.left, target); // search left
} else {
return containsRec(node.right, target); // search right
}
}
public static void main(String[] args) {
BST tree = new BST();
tree.insert(45);
tree.insert(25);
tree.insert(65);
tree.insert(15);
tree.insert(30);
System.out.println("Contains 30? " + tree.contains(30));
System.out.println("Contains 40? " + tree.contains(40));
}
Output:
Contains 30? true
Contains 40? false
Search for 30: Start at 45 (30 < 45, go left) -> 25 (30 > 25, go right) -> 30 (found!). Only 3 comparisons instead of checking all 5 nodes.
Search for 40: Start at 45 (go left) -> 25 (go right) -> 30 (go right) -> null (not found). The search eliminates half the remaining tree at each step.
Example 3: Building a BST from a Sequence
The shape of a BST depends on the insertion order. Different orders produce different trees:
public static void main(String[] args) {
// Balanced insertion order
BST balanced = new BST();
int[] order1 = {40, 20, 60, 10, 30, 50, 70};
for (int v : order1) {
balanced.insert(v);
}
System.out.print("Balanced: ");
balanced.inOrder();
// Sorted insertion order (produces a degenerate tree)
BST skewed = new BST();
int[] order2 = {10, 20, 30, 40, 50, 60, 70};
for (int v : order2) {
skewed.insert(v);
}
System.out.print("Skewed: ");
skewed.inOrder();
}
Output:
Balanced: 10 20 30 40 50 60 70
Skewed: 10 20 30 40 50 60 70
Both trees produce the same sorted output, but their shapes are very different:
Balanced: 40 Skewed: 10
/ \ \
20 60 20
/ \ / \ \
10 30 50 70 30
\
40
\
50
\
60
\
70
A skewed BST is essentially a linked list. Search becomes O(n) instead of O(log n). The BST advantage depends on the tree being reasonably balanced. Inserting sorted data produces the worst case.
Quick Code Check
Q1. In a BST, where are values smaller than the root stored?
Q2. Which traversal visits nodes in sorted (ascending) order in a BST?
Q3. What defines a leaf node in a BST?
Q4. What is the time complexity of searching in a balanced BST with n nodes?
Q5. What happens when you insert values 1, 2, 3, 4, 5 in order into an empty BST?
Trace Exercise
Insert the values 35, 15, 48, 9, 10, 30, 27 into an empty BST (in this order). Fill in where each value is placed.
| Insert value | Comparison path | Placed as |
|---|---|---|
| 35 | (empty tree) | |
| 15 | 15 < 35 | |
| 48 | 48 > 35 | |
| 9 | 9 < 35, 9 < 15 | |
| 10 | right child of 9 | |
| 30 | ||
| 27 | 27 < 35, 27 > 15, 27 < 30 |
Code Completion
Complete the recursive insert method for a BST.
Fill in the blanks:
private TreeNode insertRec(TreeNode node, int value) {
if (node == ) {
return new TreeNode(value);
}
if (value < node.) {
node.left = insertRec(node., value);
} else if (value > node.data) {
node.right = insertRec(node., value);
}
return node;
}
Complete the recursive in-order traversal.
Fill in the blanks for Left-Node-Right order:
private void inOrderRec(TreeNode node) {
if (node == null) {
return;
}
inOrderRec(node.);
System.out.print(node.data + " ");
inOrderRec(node.);
}
Spot the Bug
This insert method builds a tree where in-order traversal produces descending instead of ascending order:
Pick the correct fix for line 5:
This search method never finds values that are in the left subtree:
Pick the correct fix:
Output Prediction
What does this code print?
BST tree = new BST();
tree.insert(50);
tree.insert(30);
tree.insert(70);
tree.insert(20);
tree.insert(40);
tree.inOrder();Type the exact output:
What does this code print?
BST tree = new BST();
tree.insert(50);
tree.insert(30);
tree.insert(70);
tree.insert(20);
tree.insert(40);
System.out.println(tree.contains(40));
System.out.println(tree.contains(35));Type the exact output:
Practice Exercises
Core
- Build and traverse – Insert the values 35, 15, 48, 9, 10, 30, 27 into an empty BST. Draw the resulting tree on paper. Then run an in-order traversal and verify the output is sorted.
- Search trace – Using the tree from exercise 1, trace the comparison path to search for: (a) 30, (b) 27, (c) 50 (not in tree). How many comparisons does each search require?
- Different insertion orders – Insert the values 1-7 into a BST in these two orders: (a) 4, 2, 6, 1, 3, 5, 7 and (b) 1, 2, 3, 4, 5, 6, 7. Draw both trees. Which is balanced? Which is skewed?
Extension
- Find minimum and maximum – Write methods
public int findMin()andpublic int findMax()that return the smallest and largest values in the BST. (Hint: the smallest value is the leftmost node; the largest is the rightmost.) - Count nodes – Write a recursive method
public int size()that returns the total number of nodes in the BST. (Hint: size = 1 + size(left) + size(right), with base case: null returns 0.)
Challenge
- Pre-order and post-order – Add
preOrder()(Node-Left-Right) andpostOrder()(Left-Right-Node) traversal methods to the BST class. Test on the tree from exercise 1. Verify: pre-order starts with the root; post-order ends with the root. - Reconstruct from traversal – Given that the in-order traversal of a BST is
9, 10, 15, 27, 30, 35, 48and the pre-order traversal is35, 15, 9, 10, 30, 27, 48, draw the original tree. Explain your reconstruction strategy.
Connections
- Prerequisites: Recursion – BST operations are naturally recursive
- Prerequisites: Linked Lists – TreeNode is similar to Node but with two references instead of one
- Related: Searching Algorithms – BST search is analogous to binary search on a sorted array
- Next: BST Operations – deletion, tree height, balanced vs unbalanced, all three traversals