Binary Search Tree

Back Home

Category

Category: Trees

Topics

Topics: ordered data, range queries, in-order traversal, searching

Definition

A binary tree where each node’s left subtree contains only values less than the node, and the right subtree contains only values greater, enabling O(log n) average-case search.

Use cases

Attributes

Common operations

Operation Average Worst Description
Search O(log n) O(n) Binary search down tree
Insert O(log n) O(n) Find position, add node
Delete O(log n) O(n) Remove with successor replacement
Min/Max O(log n) O(n) Leftmost/rightmost node
In-order O(n) O(n) Sorted traversal

In code

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

class BST:
    def __init__(self):
        self.root = None

    def insert(self, val):
        if not self.root:
            self.root = TreeNode(val)
            return
        self._insert(self.root, val)

    def _insert(self, node, val):
        if val < node.val:
            if node.left:
                self._insert(node.left, val)
            else:
                node.left = TreeNode(val)
        else:
            if node.right:
                self._insert(node.right, val)
            else:
                node.right = TreeNode(val)

    def search(self, val):
        return self._search(self.root, val)

    def _search(self, node, val):
        if not node or node.val == val:
            return node
        if val < node.val:
            return self._search(node.left, val)
        return self._search(node.right, val)

    def find_min(self, node):
        """Find minimum value (leftmost node)"""
        while node.left:
            node = node.left
        return node

    def delete(self, val):
        self.root = self._delete(self.root, val)

    def _delete(self, node, val):
        if not node:
            return None
        if val < node.val:
            node.left = self._delete(node.left, val)
        elif val > node.val:
            node.right = self._delete(node.right, val)
        else:
            # Node with one or no child
            if not node.left:
                return node.right
            if not node.right:
                return node.left
            # Node with two children: get inorder successor
            successor = self.find_min(node.right)
            node.val = successor.val
            node.right = self._delete(node.right, successor.val)
        return node

Time complexity

Space complexity

O(n) for n nodes. Recursive operations use O(h) stack space. Worst case h = n (skewed), best case h = log n (balanced).

Trade-offs

Pros:

Cons:

Variants

When to use vs avoid