Step by step · Python, C++ and Java

Binary search tree insertion, visualized

A binary search tree keeps every value in a node’s left subtree smaller than it, and every value in its right subtree larger. That one rule makes search, insert and delete take time proportional to the tree’s height.

How it works
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None


def insert(node, val):
    if node is None:
        return TreeNode(val)
    if val < node.val:
        node.left = insert(node.left, val)
    elif val > node.val:
        node.right = insert(node.right, val)
    return node


root = None
for value in [50, 30, 70, 20, 40, 60, 80]:
    root = insert(root, value)

print("built")

How binary search tree insertion works

To insert, start at the root and compare: smaller goes left, larger goes right, until you reach an empty child, where the new node is attached. The recursive version returns the subtree’s root at every level, so each parent re-links its child on the way back up.

The Python example inserts 50, 30, 70, 20, 40, 60, 80, which produces a perfectly balanced tree three levels deep.

What to watch for when it runs

  1. The path each value takes down from the root is highlighted as it descends.
  2. New nodes only ever appear as leaves — insertion never rearranges existing nodes.
  3. Insert the same values in sorted order and the tree degenerates into a chain, making every operation O(n).

Time and space complexity

Time
O(h) per insert — O(log n) balanced, O(n) worst case
Space
O(h) recursion

h is the height of the tree. Self-balancing trees (AVL, red-black) exist to keep h at O(log n) whatever order values arrive in.

Stuck on your own version?

Paste it into the visualizer and watch your own code run, line by line — bugs included.