Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Data Structures, Lightly  ›  Lesson

Binary Search Trees

Binary Search Tree 15 minLeft is smaller, right is bigger — one rule that lets search skip half the tree at every step
Your task
Write sorted_via_bst(values). Build a binary search tree by inserting every value in values in order, then return an inorder traversal. Example: sorted_via_bst([5, 3, 8, 1, 4, 7, 9]) -> [1, 3, 4, 5, 7, 8, 9].

Binary Search Trees

In short: a binary search tree keeps one rule at every single node: everything in its left subtree is smaller, everything in its right subtree is bigger. That rule alone means search and insert can skip half the remaining tree at every step, the same idea as binary search on a sorted list — except the tree can grow without ever shifting anything. Python has no built-in BST the way it has list or dict; this is the one structure on this tour you'd actually write a Node class for yourself. (In practice, sorted() plus the bisect module covers most "keep this searchable" needs without one — the DSA course covers when a real BST earns its keep, and how to keep it balanced.)

A small tree: root 5 with an arrow left to 3 labelled "smaller" and an arrow right to 8 labelled "bigger"; 3 has a left child 1 and right child 4; 8 has a left child 7 and right child 9 — a dashed path 5 → 8 → 7 is highlighted, labelled "search for 7: skip the entire left half at the root"

File a document by ID number

A records office keeps folders in one cabinet, filed by ID number, using the same rule at every drawer: smaller numbers to the left, bigger to the right. Building that cabinet is just repeated insertion — walk down from the root, going left or right by comparing, until there's an empty spot:

python

Walk left-subtree, node, right-subtree — in that order — and a BST hands you its values back sorted, no matter what order the files were filed in. That's not a coincidence; it's the left-smaller-right-bigger rule read aloud. The mistake people make is assuming that order, once built, has to be re-sorted to read out — it doesn't. The structure already encodes it.

Search for a folder: skip half the cabinet at each step

Looking something up never checks more than one path from root to leaf:

python

At the root (5), searching for folder 7 goes right — the entire left subtree (1, 3, 4) is skipped, never even looked at. That's the whole payoff: each comparison throws away a whole branch, not just one value, the same way a librarian skips entire shelves instead of checking every book.

The mistake that breaks this isn't in the search code at all — it's filing a folder on the wrong side in the first place. contains trusts the tree's own rule; if a value ever ends up on the wrong side, the search will walk straight past it without ever knowing it's there:

broken — fix it

Run it — contains(root, 9) wrongly says False, because the tree itself broke its own rule. Fix where 9 was placed, not the search.

Always build a tree through insert, never by hand-wiring .left/.right directly — that's the only way the rule stays true at every node, and the only reason contains is allowed to trust it.

Quick practice

What does this print?
root = None
def insert(root, val):
    if root is None:
        return Node(val)
    if val < root.val:
        root.left = insert(root.left, val)
    else:
        root.right = insert(root.right, val)
    return root

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

for v in [10, 5, 15, 3]:
    root = insert(root, v)
print(root.left.left.val)
What does this print?
class Node:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

root = Node(5)
root.left = Node(2)
root.right = Node(9)

def contains(root, target):
    node = root
    while node:
        if target == node.val:
            return True
        node = node.left if target < node.val else node.right
    return False

print(contains(root, 2), contains(root, 7))

🎯 Your turn

Write sorted_via_bst(values). Build a binary search tree by inserting every value in values in order, then return an inorder traversal — proving the tree already holds them sorted:

  • sorted_via_bst([5, 3, 8, 1, 4, 7, 9]) → [1, 3, 4, 5, 7, 8, 9]
  • sorted_via_bst([]) → []

Hint — build the tree with insert exactly as in the lesson, then inorder(n.left) + [n.val] + inorder(n.right).

Press ▶ Run, try the Live App chips, then ✓ Check. After that, the practice set below walks to the smallest and largest values, and counts how deep the tree actually grew.

Practice — level up

0/5 solved

Solve each in its own editor — Run to try, Check to grade. Stuck? Reveal a Hint, or the full Solution + walkthrough.

Warm-upThe smallest value, by walking left

Write bst_min(values). Build a BST from values, then walk .left until there's nowhere left to go, and return that value. Return None for an empty input.

binary-search-treesbst-insert
DrillSearch without checking every value

Write bst_contains(values, target). Build a BST from values, then search for target by comparing and stepping left or right — never checking a value the BST rule already ruled out.

binary-search-treesbst-search
BuildThe largest value, by walking right

Write bst_max(values). Build a BST, then walk .right until there's nowhere further to go, and return that value. Return None for an empty input.

binary-search-trees
BossHow deep did the tree grow?

Write bst_height(values). Build a BST, then return its height: an empty tree has height 0, and any node's height is 1 + the taller of its two subtrees.

binary-search-treestree-height
CapstoneThe k-th smallest value

Write kth_smallest(values, k). Build a BST, then use an inorder traversal to find the k-th smallest value (1-indexed: k=1 is the smallest).

binary-search-treesbst-range
sorted_via_bst.py
Call the function you wrote — just like your app's frontend would. Edit the inputs and hit Call.
sorted_via_bst(values) → listInsert every value into a BST, then read it back out sorted with an inorder walk.
try:
returned
No app map for this section yet.
Press Run to execute your code.
Press Check to run the tests for this lesson.