{
  "id": "trees/binary-search-tree",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/trees/binary-search-tree",
  "topic": {
    "slug": "trees",
    "title": "Trees"
  },
  "title": "Binary Search Tree",
  "tagline": "A tree that keeps one promise — smaller left, bigger right — so it can search fast.",
  "vizKind": "tree",
  "complexity": {
    "time": {
      "best": "O(log n)",
      "average": "O(log n)",
      "worst": "O(n)"
    },
    "space": "O(n)",
    "growth": "log",
    "note": "Search, insert and delete all cost about the height of the tree. A balanced tree has height log n — beautifully fast. But insert sorted values and the tree degenerates into a line of height n, and everything slows to a crawl. Balance is everything."
  },
  "code": {
    "javascript": "function insert(root, value) {\n  if (root === null) return new Node(value);\n  if (value < root.value) {\n    root.left = insert(root.left, value);\n  } else {\n    root.right = insert(root.right, value);\n  }\n  return root;\n}\n\nfunction search(root, value) {\n  if (root === null) return false;\n  if (value === root.value) return true;\n  if (value < root.value) {\n    return search(root.left, value);\n  }\n  return search(root.right, value);\n}",
    "python": "def insert(root, value):\n    if root is None: return Node(value)\n    if value < root.value:\n        root.left = insert(root.left, value)\n    else:\n        root.right = insert(root.right, value)\n\n    return root\n\n\ndef search(root, value):\n    if root is None: return False\n    if value == root.value: return True\n    if value < root.value:\n        return search(root.left, value)\n\n    return search(root.right, value)\n",
    "java": "Node insert(Node root, int value) {\n  if (root == null) return new Node(value);\n  if (value < root.value) {\n    root.left = insert(root.left, value);\n  } else {\n    root.right = insert(root.right, value);\n  }\n  return root;\n}\n\nboolean search(Node root, int value) {\n  if (root == null) return false;\n  if (value == root.value) return true;\n  if (value < root.value) {\n    return search(root.left, value);\n  }\n  return search(root.right, value);\n}",
    "cpp": "Node* insert(Node* root, int value) {\n  if (root == nullptr) return new Node(value);\n  if (value < root->value) {\n    root->left = insert(root->left, value);\n  } else {\n    root->right = insert(root->right, value);\n  }\n  return root;\n}\n\nbool search(Node* root, int value) {\n  if (root == nullptr) return false;\n  if (value == root->value) return true;\n  if (value < root->value) {\n    return search(root->left, value);\n  }\n  return search(root->right, value);\n}"
  },
  "defaultInput": [
    50,
    30,
    70,
    20,
    40,
    60,
    80
  ],
  "defaultTarget": 40,
  "inputHint": "These get inserted one by one, then we search for the target.",
  "pitfalls": [
    {
      "wrong": "Inserting already-sorted data and expecting it to stay fast.",
      "right": "Sorted input builds a tree that's really just a linked list — height n, not log n. That's the worst case, and it's why self-balancing trees exist."
    },
    {
      "wrong": "Putting equal values on both sides inconsistently.",
      "right": "Pick one rule — say, equal goes right — and apply it everywhere. Mixing the rule breaks search, because a value could hide on the side you didn't check."
    },
    {
      "wrong": "Forgetting the empty-tree case when inserting.",
      "right": "If the root is null, the new value becomes the root. Skip that check and the very first insert crashes."
    }
  ],
  "quiz": [
    {
      "q": "In a binary search tree, where do you find values smaller than a node?",
      "options": [
        "In its right branch",
        "In its left branch",
        "Anywhere below it",
        "Only at the root"
      ],
      "answer": 1,
      "why": "The core promise: smaller values live in the left branch, bigger ones in the right. That's what lets search discard half the tree at every step."
    },
    {
      "q": "Searching a balanced BST of 1,000,000 nodes takes about how many steps?",
      "options": [
        "1,000,000",
        "500,000",
        "About 20",
        "About 1,000"
      ],
      "answer": 2,
      "why": "A balanced tree has height log₂(n) ≈ 20 for a million nodes. Each step drops a whole branch — the same logarithmic magic as binary search."
    },
    {
      "q": "What happens if you insert values in already-sorted order?",
      "options": [
        "The tree stays perfectly balanced",
        "The tree becomes a straight line, height n",
        "The insert fails",
        "It automatically rebalances"
      ],
      "answer": 1,
      "why": "Each new value is bigger than the last, so it always goes right — the tree stretches into a line of height n and search degrades to O(n). This is exactly the problem self-balancing trees solve."
    }
  ],
  "problems": [
    {
      "name": "Search in a Binary Search Tree",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/search-in-a-binary-search-tree/"
    },
    {
      "name": "Insert into a Binary Search Tree",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/insert-into-a-binary-search-tree/"
    },
    {
      "name": "Validate Binary Search Tree",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/validate-binary-search-tree/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 22,
    "frames": [
      {
        "data": {
          "nodes": [],
          "rootId": null
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 1,
        "variables": {},
        "explanation": "A binary search tree keeps a promise at every node: smaller values live to the left, bigger values to the right. That one rule is what makes it fast to search.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        }
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": null,
              "right": null,
              "role": "found"
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 2,
        "variables": {
          "inserting": 50
        },
        "explanation": "The tree is empty, so 50 becomes the root — the top of the tree.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": null,
              "right": null,
              "role": "compare"
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 3,
        "variables": {
          "inserting": 30,
          "at": 50,
          "go": "left"
        },
        "explanation": "30 is smaller than 50, so go left.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": null,
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": null,
              "right": null,
              "role": "found"
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 2,
        "variables": {
          "inserted": 30,
          "depth": 1
        },
        "explanation": "We ran off the bottom of the tree, so that empty spot is where 30 belongs. It took 1 comparison to place it.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": null,
              "role": "compare"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "inserting": 70,
          "at": 50,
          "go": "right"
        },
        "explanation": "70 is not smaller than 50, so go right.",
        "stats": {
          "comparisons": 2,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": null,
              "right": null
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": null,
              "right": null,
              "role": "found"
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 2,
        "variables": {
          "inserted": 70,
          "depth": 1
        },
        "explanation": "We ran off the bottom of the tree, so that empty spot is where 70 belongs. It took 1 comparison to place it.",
        "stats": {
          "comparisons": 2,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "compare"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": null,
              "right": null
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 3,
        "variables": {
          "inserting": 20,
          "at": 50,
          "go": "left"
        },
        "explanation": "20 is smaller than 50, so go left.",
        "stats": {
          "comparisons": 3,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": null,
              "right": null,
              "role": "compare"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 3,
        "variables": {
          "inserting": 20,
          "at": 30,
          "go": "left"
        },
        "explanation": "20 is smaller than 30, so go left.",
        "stats": {
          "comparisons": 4,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": null,
              "role": "active"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": null,
              "right": null
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null,
              "role": "found"
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 2,
        "variables": {
          "inserted": 20,
          "depth": 2
        },
        "explanation": "We ran off the bottom of the tree, so that empty spot is where 20 belongs. It took 2 comparisons to place it.",
        "stats": {
          "comparisons": 4,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "compare"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": null
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": null,
              "right": null
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 3,
        "variables": {
          "inserting": 40,
          "at": 50,
          "go": "left"
        },
        "explanation": "40 is smaller than 50, so go left.",
        "stats": {
          "comparisons": 5,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": null,
              "role": "compare"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": null,
              "right": null
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "inserting": 40,
          "at": 30,
          "go": "right"
        },
        "explanation": "40 is not smaller than 30, so go right.",
        "stats": {
          "comparisons": 6,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40",
              "role": "active"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": null,
              "right": null
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null,
              "role": "found"
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 2,
        "variables": {
          "inserted": 40,
          "depth": 2
        },
        "explanation": "We ran off the bottom of the tree, so that empty spot is where 40 belongs. It took 2 comparisons to place it.",
        "stats": {
          "comparisons": 6,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "compare"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": null,
              "right": null
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "inserting": 60,
          "at": 50,
          "go": "right"
        },
        "explanation": "60 is not smaller than 50, so go right.",
        "stats": {
          "comparisons": 7,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": null,
              "right": null,
              "role": "compare"
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 3,
        "variables": {
          "inserting": 60,
          "at": 70,
          "go": "left"
        },
        "explanation": "60 is smaller than 70, so go left.",
        "stats": {
          "comparisons": 8,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": "t5-60",
              "right": null,
              "role": "active"
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null
            },
            {
              "id": "t5-60",
              "value": 60,
              "left": null,
              "right": null,
              "role": "found"
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 2,
        "variables": {
          "inserted": 60,
          "depth": 2
        },
        "explanation": "We ran off the bottom of the tree, so that empty spot is where 60 belongs. It took 2 comparisons to place it.",
        "stats": {
          "comparisons": 8,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "compare"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": "t5-60",
              "right": null
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null
            },
            {
              "id": "t5-60",
              "value": 60,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "inserting": 80,
          "at": 50,
          "go": "right"
        },
        "explanation": "80 is not smaller than 50, so go right.",
        "stats": {
          "comparisons": 9,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": "t5-60",
              "right": null,
              "role": "compare"
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null
            },
            {
              "id": "t5-60",
              "value": 60,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "inserting": 80,
          "at": 70,
          "go": "right"
        },
        "explanation": "80 is not smaller than 70, so go right.",
        "stats": {
          "comparisons": 10,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": "t5-60",
              "right": "t6-80",
              "role": "active"
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null
            },
            {
              "id": "t5-60",
              "value": 60,
              "left": null,
              "right": null
            },
            {
              "id": "t6-80",
              "value": 80,
              "left": null,
              "right": null,
              "role": "found"
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 2,
        "variables": {
          "inserted": 80,
          "depth": 2
        },
        "explanation": "We ran off the bottom of the tree, so that empty spot is where 80 belongs. It took 2 comparisons to place it.",
        "stats": {
          "comparisons": 10,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": "t5-60",
              "right": "t6-80"
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null
            },
            {
              "id": "t5-60",
              "value": 60,
              "left": null,
              "right": null
            },
            {
              "id": "t6-80",
              "value": 80,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 12,
        "variables": {},
        "explanation": "Now search for 40. Searching is the same walk: at each node, go left if smaller, right if bigger.",
        "stats": {
          "comparisons": 10,
          "swaps": 0
        },
        "accent": "active"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "compare"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": "t5-60",
              "right": "t6-80"
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null
            },
            {
              "id": "t5-60",
              "value": 60,
              "left": null,
              "right": null
            },
            {
              "id": "t6-80",
              "value": 80,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 15,
        "variables": {
          "target": 40,
          "at": 50,
          "go": "left"
        },
        "explanation": "40 vs 50: go left, and ignore the entire right subtree.",
        "stats": {
          "comparisons": 11,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40",
              "role": "compare"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": "t5-60",
              "right": "t6-80"
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null
            },
            {
              "id": "t5-60",
              "value": 60,
              "left": null,
              "right": null
            },
            {
              "id": "t6-80",
              "value": 80,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 17,
        "variables": {
          "target": 40,
          "at": 30,
          "go": "right"
        },
        "explanation": "40 vs 30: go right, and ignore the entire left subtree.",
        "stats": {
          "comparisons": 12,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "t0-50",
              "value": 50,
              "left": "t1-30",
              "right": "t2-70",
              "role": "active"
            },
            {
              "id": "t1-30",
              "value": 30,
              "left": "t3-20",
              "right": "t4-40",
              "role": "active"
            },
            {
              "id": "t2-70",
              "value": 70,
              "left": "t5-60",
              "right": "t6-80"
            },
            {
              "id": "t3-20",
              "value": 20,
              "left": null,
              "right": null
            },
            {
              "id": "t4-40",
              "value": 40,
              "left": null,
              "right": null,
              "role": "found"
            },
            {
              "id": "t5-60",
              "value": 60,
              "left": null,
              "right": null
            },
            {
              "id": "t6-80",
              "value": 80,
              "left": null,
              "right": null
            }
          ],
          "rootId": "t0-50"
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 14,
        "variables": {
          "target": 40,
          "looks": 3
        },
        "explanation": "Found 40 after 3 looks — never once looking at the other half of the tree.",
        "stats": {
          "comparisons": 13,
          "swaps": 0
        },
        "accent": "found"
      }
    ]
  }
}