Skip to main content
Back to the DSA atlas
GraphsTrees Data structure Intermediate

Binary Search Tree (BST)

A sorted tree structure enabling O(log n) search, insert, and delete. Foundation for balanced trees, sets, and maps.

Trees is nested under Graphs , so techniques in the broader family usually still apply here.

treebstbinary-searchrecursion

Interactive visualization

Use the controls to connect the idea to concrete operations before diving into the full write-up.

Speed: 500ms
Unvisited Comparing Current Found Deleted

Family

Graphs → Trees

Hierarchies and constrained graphs. A tree is a connected acyclic graph.

Builds on

2 topics

Read these first if you want the surrounding context.

Unlocks

4 next topics

Use these follow-ups when you want to apply the current idea in a richer setting.

Learning paths

2

This topic appears in curated progressions so you can keep moving without guessing the next step.

Problem

Store a dynamic set of elements supporting search, insert, and delete — all in O(logn)O(\log n) average time — while maintaining sorted order.

Intuition

A BST is a binary tree where every node satisfies the BST invariant: all values in the left subtree are strictly less than the node, and all values in the right subtree are strictly greater. This single rule turns a tree into a searchable structure — at every node you know which half to recurse into, just like binary search on an array, but with the flexibility of a linked structure.

The key insight: binary search requires a sorted array, which makes insertions O(n)O(n). A BST gives you the same halving principle in a structure where inserts and deletes are local pointer operations.

Algorithm

search(node, target):
    if node is null: return null
    if target == node.val: return node
    if target < node.val: return search(node.left, target)
    else: return search(node.right, target)

Insert

insert(node, val):
    if node is null: return new Node(val)
    if val < node.val: node.left ← insert(node.left, val)
    else if val > node.val: node.right ← insert(node.right, val)
    return node

Delete (three cases)

delete(node, val):
    if node is null: return null
    if val < node.val: node.left ← delete(node.left, val)
    else if val > node.val: node.right ← delete(node.right, val)
    else:
        // Case 1: leaf — just remove
        if node.left is null and node.right is null: return null
        // Case 2: one child — replace with child
        if node.left is null: return node.right
        if node.right is null: return node.left
        // Case 3: two children — replace with inorder successor
        successor ← min(node.right)
        node.val ← successor.val
        node.right ← delete(node.right, successor.val)
    return node

Inorder traversal

inorder(node):
    if node is null: return
    inorder(node.left)
    visit(node)
    inorder(node.right)

BST property and its consequences

Inorder traversal yields sorted order. This is a direct consequence of the invariant — left subtree (smaller values) is visited first, then the node, then right subtree (larger values). This means you get a free O(n)O(n) sort from any BST.

Successor: the next larger element is either the leftmost node in the right subtree, or the nearest ancestor where the node is in the left subtree. Predecessor is symmetric. Both are O(h)O(h) where hh is the tree height.

Min/Max: follow left (or right) pointers to the end. O(h)O(h).

Balancing

An unbalanced BST degenerates to a linked list. Inserting sorted data [1,2,3,,n][1, 2, 3, \ldots, n] creates a chain of right children — every operation becomes O(n)O(n). This is the fundamental weakness of naive BSTs.

Self-balancing variants fix this by enforcing height constraints:

  • AVL trees: height difference between subtrees 1\leq 1. Strict balance, faster lookups, more rotations on insert/delete.
  • Red-Black trees: nodes are colored red/black with rules ensuring no path is more than 2×2\times longer than any other. Used in most standard library implementations (std::map, TreeMap).

Both guarantee O(logn)O(\log n) height. The details of rotations are important but orthogonal to understanding the BST concept itself.

Common patterns

Validate BST: inorder traversal should be strictly increasing — or recursively pass (min,max)(\text{min}, \text{max}) bounds down the tree.

Kth smallest element: augment each node with a subtree size count, or do an inorder traversal with a counter.

Lowest Common Ancestor (LCA) in BST: if both values are less than the current node, go left. If both greater, go right. Otherwise, the current node is the LCA. O(h)O(h) — simpler than generic tree LCA because the BST invariant tells you which direction to go.

BST iterator: use a stack to simulate inorder traversal. Push all left children, pop to get next, then push left children of the right child. Amortized O(1)O(1) per next() call.

Complexity

OperationAverageWorst (unbalanced)
SearchO(logn)O(\log n)O(n)O(n)
InsertO(logn)O(\log n)O(n)O(n)
DeleteO(logn)O(\log n)O(n)O(n)
InorderO(n)O(n)O(n)O(n)
Min/MaxO(logn)O(\log n)O(n)O(n)
SpaceO(n)O(n)O(n)O(n)

Balanced variants (AVL, Red-Black) guarantee O(logn)O(\log n) worst case for search, insert, and delete.

Key takeaways

  • Inorder traversal gives sorted order for free — this single property is the basis for validation, kth-smallest, and iterator problems.
  • Unbalanced BSTs degrade to O(n)O(n) — inserting sorted data creates a linked list; always consider whether the problem guarantees balance or if you need a self-balancing variant.
  • LCA in a BST is simpler than in a generic tree — the BST invariant tells you exactly which direction to go, giving an O(h)O(h) solution without parent pointers or preprocessing.
  • Delete has three cases — leaf, one child, two children. The two-children case uses the inorder successor (or predecessor) and is the most common interview follow-up.
  • BST = binary search as a data structure — arrays give O(logn)O(\log n) search but O(n)O(n) insert; BSTs give O(logn)O(\log n) for both by trading contiguous memory for pointers.

Practice problems

ProblemDifficultyKey idea
Validate Binary Search Tree🟡 MediumPass min/max bounds recursively or check that inorder traversal is strictly increasing
Kth Smallest Element in a BST🟡 MediumInorder traversal with a counter; stop early once you’ve visited kk nodes
Lowest Common Ancestor of a Binary Search Tree🟡 MediumUse the BST invariant to decide left/right — split point is the LCA
Convert Sorted Array to Binary Search Tree🟢 EasyRecursively pick the middle element as root to guarantee balanced height
Delete Node in a BST🟡 MediumHandle the three deletion cases, replacing with inorder successor for two-children nodes

Relation to other topics

  • Binary search: a BST is essentially binary search materialized as a data structure. The array gives you O(logn)O(\log n) search but O(n)O(n) insert; the BST gives you O(logn)O(\log n) for both.
  • Heaps: both are tree-based, but heaps only guarantee a partial order (parent vs children). BSTs maintain a total order (left < node < right). You can’t efficiently search a heap, and you can’t efficiently extract-min from a BST without augmentation.
  • Balanced BSTs → sets and maps: virtually every language’s sorted set/map (TreeSet, std::set, BTreeMap) is a balanced BST underneath. When you need ordered iteration, range queries, or floor/ceiling operations, you’re using a BST.

Build on these first

These topics supply the mental model or underlying structure that this page assumes.

What this enables

Once the current idea feels natural, these are the most useful next jumps.

Related directions

These topics live nearby conceptually, even if they are not direct prerequisites.

More from Trees

Stay in the same family when you want parallel variations of the same mental model.

Paths that include this topic

Follow one of these sequences if you want a guided next step instead of open-ended browsing.

Ordered structures

See how order can come from sorted arrays, search trees, skip lists, disk-friendly indexes, heaps, and prefix trees.

Storage engines

Compare fanout-heavy indexes, write-optimized trees, and external-memory sorting in one storage-oriented path.

From the blog

Pair the atlas with recent writing from the rest of the site when you want a broader engineering perspective alongside the topic graph.