🌲 Binary Search Tree (BST)

🟡 Intermediate Non-Linear DS 75 min read

🎯 What is a BST?

A Binary Search Tree is a binary tree with the property: for every node, all values in the left subtree are smaller, and all values in the right subtree are larger. This enables O(log n) search, insert, and delete in a balanced BST.
       8           BST Property:
     /   \         Left < Root < Right
    3     10       ✅ 3 < 8 < 10
   / \      \      ✅ 1 < 3 < 6
  1   6     14     ✅ 6 < 8
     / \   /
    4   7 13

💻 PHP Implementation

<?php
class BSTNode {
    public int $val;
    public ?BSTNode $left = null, $right = null;
    public function __construct(int $val) { $this->val = $val; }
}

class BST {
    public ?BSTNode $root = null;

    // Insert - O(log n) avg, O(n) worst
    public function insert(int $val): void {
        $this->root = $this->insertRec($this->root, $val);
    }

    private function insertRec(?BSTNode $node, int $val): BSTNode {
        if ($node === null) return new BSTNode($val);
        if ($val < $node->val) $node->left = $this->insertRec($node->left, $val);
        else $node->right = $this->insertRec($node->right, $val);
        return $node;
    }

    // Search - O(log n) avg, O(n) worst
    public function search(int $val): bool {
        return $this->searchRec($this->root, $val) !== null;
    }

    private function searchRec(?BSTNode $node, int $val): ?BSTNode {
        if ($node === null || $node->val === $val) return $node;
        if ($val < $node->val) return $this->searchRec($node->left, $val);
        return $this->searchRec($node->right, $val);
    }

    // Delete - O(log n) avg
    public function delete(int $val): void {
        $this->root = $this->deleteRec($this->root, $val);
    }

    private function deleteRec(?BSTNode $node, int $val): ?BSTNode {
        if ($node === null) return null;

        if ($val < $node->val) $node->left = $this->deleteRec($node->left, $val);
        elseif ($val > $node->val) $node->right = $this->deleteRec($node->right, $val);
        else {
            // Case 1 & 2: 0 or 1 child
            if ($node->left === null) return $node->right;
            if ($node->right === null) return $node->left;
            // Case 3: 2 children - find inorder successor
            $minNode = $this->findMin($node->right);
            $node->val = $minNode->val;
            $node->right = $this->deleteRec($node->right, $minNode->val);
        }
        return $node;
    }

    private function findMin(BSTNode $node): BSTNode {
        while ($node->left !== null) $node = $node->left;
        return $node;
    }

    // Validate BST
    public function isValidBST(): bool {
        return $this->validate($this->root, PHP_INT_MIN, PHP_INT_MAX);
    }

    private function validate(?BSTNode $node, int $min, int $max): bool {
        if ($node === null) return true;
        if ($node->val <= $min || $node->val >= $max) return false;
        return $this->validate($node->left, $min, $node->val)
            && $this->validate($node->right, $node->val, $max);
    }

    // Inorder gives sorted order!
    public function inorder(): array {
        $result = []; $this->inorderRec($this->root, $result);
        return $result;
    }

    private function inorderRec(?BSTNode $node, array &$result): void {
        if ($node === null) return;
        $this->inorderRec($node->left, $result);
        $result[] = $node->val;
        $this->inorderRec($node->right, $result);
    }
}

$bst = new BST();
foreach ([8,3,10,1,6,14,4,7,13] as $v) $bst->insert($v);
var_dump($bst->search(6));   // true
var_dump($bst->search(99)); // false
print_r($bst->inorder());    // [1,3,4,6,7,8,10,13,14] - SORTED!
var_dump($bst->isValidBST()); // true

📊 Complexity

Operation Average (Balanced) Worst (Skewed)
Search O(log n) O(n)
Insert O(log n) O(n)
Delete O(log n) O(n)
Min/Max O(log n) O(n)
⚠️ BST becomes O(n) when skewed (e.g., inserting sorted data: 1,2,3,4,5 creates a linked list). Use AVL or Red-Black trees for guaranteed O(log n).

💼 Interview Questions

Keep going left until null. The leftmost node is the minimum. Similarly, rightmost node is maximum. O(h) time.

Replace with inorder successor (smallest in right subtree) or inorder predecessor (largest in left subtree). Then delete that successor/predecessor (which has ≤1 child).

📝 Quick Quiz

Q1: BST inorder traversal produces elements in:

Q2: What happens if you insert sorted data [1,2,3,4,5] into a BST?