Daily Tech Brief

Top startup stories in your inbox

Subscribe Free

© 2026 rakrisi Daily

Binary Search Trees - Like a Phone Book

Binary Search Trees: Like a Phone Book

Welcome back! You learned about basic binary trees (like family trees). Now let’s learn about Binary Search Trees - special trees that keep data organized for super-fast searching!

What Makes a BST Special? (Phone Book Analogy)

The Phone Book Rule

Imagine a phone book where names are organized alphabetically:

  • A names come first
  • Z names come last
  • Everything is in perfect alphabetical order

A Binary Search Tree follows similar rules:

  • Left side: Smaller values (like A-M in phone book)
  • Right side: Larger values (like N-Z in phone book)
  • Perfect order: Everything stays organized automatically!

The Magic Rule

BST Rule: For any number in the tree:

  • Everything in its left subtree is smaller
  • Everything in its right subtree is larger

Building Your First BST

Let’s create a phone book tree:

// A contact in our phone book
type Contact struct {
    name  string
    phone string
    left  *Contact  // People with names before this one
    right *Contact  // People with names after this one
}

// Our phone book
type PhoneBook struct {
    root *Contact
}

Adding Contacts (Insert)

func (pb *PhoneBook) addContact(name, phone string) {
    pb.root = addContactHelper(pb.root, name, phone)
}

func addContactHelper(node *Contact, name, phone string) *Contact {
    // Empty spot? Add contact here!
    if node == nil {
        return &Contact{name: name, phone: phone}
    }
    
    // Compare names alphabetically
    if name < node.name {
        // Name comes before - go left
        node.left = addContactHelper(node.left, name, phone)
    } else if name > node.name {
        // Name comes after - go right
        node.right = addContactHelper(node.right, name, phone)
    }
    // Same name? Skip (no duplicates)
    
    return node
}

// Let's add some contacts
book := &PhoneBook{}
book.addContact("Alice", "555-0101")
book.addContact("Bob", "555-0102")
book.addContact("Charlie", "555-0103")
book.addContact("Zoe", "555-0199")

// The tree looks like:
//      Charlie
//     /       \
//  Bob       Zoe
//  /
// Alice
func (pb *PhoneBook) findContact(name string) string {
    return findContactHelper(pb.root, name)
}

func findContactHelper(node *Contact, name string) string {
    // Not found!
    if node == nil {
        return "Contact not found"
    }
    
    if name == node.name {
        // Found it!
        return node.phone
    } else if name < node.name {
        // Look left (earlier in alphabet)
        return findContactHelper(node.left, name)
    } else {
        // Look right (later in alphabet)
        return findContactHelper(node.right, name)
    }
}

// Search examples
phone := book.findContact("Bob")        // "555-0102"
phone := book.findContact("David")      // "Contact not found"

Real Life Example: Number Organizer

type NumberTree struct {
    root *NumberNode
}

type NumberNode struct {
    value int
    left  *NumberNode
    right *NumberNode
}

func (nt *NumberTree) insert(num int) {
    nt.root = insertHelper(nt.root, num)
}

func insertHelper(node *NumberNode, num int) *NumberNode {
    if node == nil {
        return &NumberNode{value: num}
    }
    
    if num < node.value {
        node.left = insertHelper(node.left, num)
    } else if num > node.value {
        node.right = insertHelper(node.right, num)
    }
    // Skip duplicates
    
    return node
}

func (nt *NumberTree) search(num int) bool {
    return searchHelper(nt.root, num)
}

func searchHelper(node *NumberNode, num int) bool {
    if node == nil {
        return false
    }
    
    if num == node.value {
        return true
    } else if num < node.value {
        return searchHelper(node.left, num)
    } else {
        return searchHelper(node.right, num)
    }
}

func main() {
    tree := &NumberTree{}
    
    // Add numbers
    numbers := []int{50, 30, 70, 20, 40, 60, 80}
    for _, num := range numbers {
        tree.insert(num)
    }
    
    // The tree:
    //      50
    //     /  \
    //   30    70
    //  / \   / \
    // 20 40 60 80
    
    // Search
    fmt.Println(tree.search(40))  // true
    fmt.Println(tree.search(25))  // false
}

Why BSTs Are Super Fast

Finding a number in a list:

  • List: [20, 30, 40, 50, 60, 70, 80]
  • Check each number one by one (slow!)

Finding a number in BST:

  • Start at 50
  • 40 < 50? Go left to 30
  • 40 > 30? Go right to 40
  • Found in 3 steps!

Speed comparison:

  • List: Check up to 7 numbers
  • BST: Check only 3 numbers (logâ‚‚7 ≈ 2.8)

Finding Extreme Values

Find Smallest Number (Leftmost)

func (nt *NumberTree) findSmallest() int {
    if nt.root == nil {
        return -1
    }
    
    // Keep going left until you can't go further
    current := nt.root
    for current.left != nil {
        current = current.left
    }
    
    return current.value
}

// In our tree: finds 20

Find Largest Number (Rightmost)

func (nt *NumberTree) findLargest() int {
    if nt.root == nil {
        return -1
    }
    
    // Keep going right until you can't go further
    current := nt.root
    for current.right != nil {
        current = current.right
    }
    
    return current.value
}

// In our tree: finds 80

The Special Power: In-Order Traversal

When you traverse a BST in-order (left, root, right), you get everything in sorted order!

func (nt *NumberTree) getSortedNumbers() []int {
    result := []int{}
    inOrderHelper(nt.root, &result)
    return result
}

func inOrderHelper(node *NumberNode, result *[]int) {
    if node == nil {
        return
    }
    
    // Left first
    inOrderHelper(node.left, result)
    
    // Then current
    *result = append(*result, node.value)
    
    // Then right
    inOrderHelper(node.right, result)
}

// Result: [20, 30, 40, 50, 60, 70, 80] - perfectly sorted!

Real Life Example: Dictionary Tree

type Dictionary struct {
    root *WordNode
}

type WordNode struct {
    word  string
    left  *WordNode
    right *WordNode
}

func (d *Dictionary) addWord(word string) {
    d.root = addWordHelper(d.root, word)
}

func addWordHelper(node *WordNode, word string) *WordNode {
    if node == nil {
        return &WordNode{word: word}
    }
    
    if word < node.word {
        node.left = addWordHelper(node.left, word)
    } else if word > node.word {
        node.right = addWordHelper(node.right, word)
    }
    
    return node
}

func (d *Dictionary) findWord(word string) bool {
    return findWordHelper(d.root, word)
}

func findWordHelper(node *WordNode, word string) bool {
    if node == nil {
        return false
    }
    
    if word == node.word {
        return true
    } else if word < node.word {
        return findWordHelper(node.left, word)
    } else {
        return findWordHelper(node.right, word)
    }
}

func (d *Dictionary) getAllWords() []string {
    result := []string{}
    collectWords(d.root, &result)
    return result
}

func collectWords(node *WordNode, result *[]string) {
    if node == nil {
        return
    }
    
    collectWords(node.left, result)
    *result = append(*result, node.word)
    collectWords(node.right, result)
}

func main() {
    dict := &Dictionary{}
    
    words := []string{"apple", "banana", "cherry", "date", "elderberry"}
    for _, word := range words {
        dict.addWord(word)
    }
    
    // All words in alphabetical order
    allWords := dict.getAllWords()
    fmt.Println(allWords)  // [apple, banana, cherry, date, elderberry]
    
    // Search
    fmt.Println(dict.findWord("cherry"))  // true
    fmt.Println(dict.findWord("grape"))   // false
}

BST Challenges

Challenge 1: Number Range Finder

Find all numbers between two values:

func (nt *NumberTree) findInRange(low, high int) []int {
    result := []int{}
    // Your code here
    // Hint: Use in-order traversal with range check
    return result
}

Challenge 2: Tree Height Calculator

Calculate how tall the tree is:

func (nt *NumberTree) getHeight() int {
    // Your code here
    // Hint: Max of left height + right height + 1
    return 0
}

Challenge 3: Closest Number Finder

Find the number in the tree closest to a target:

func (nt *NumberTree) findClosest(target int) int {
    // Your code here
    // Hint: Keep track of closest as you search
    return 0
}

Challenge 4: Tree Balancer

Check if the tree is balanced (similar heights on both sides):

func (nt *NumberTree) isBalanced() bool {
    // Your code here
    // Hint: Compare left and right subtree heights
    return false
}

Challenge 5: Duplicate Counter

Count how many times each number appears:

func (nt *NumberTree) countDuplicates() map[int]int {
    // Your code here
    // Hint: Use a map to count during traversal
    return nil
}

Real World Uses of BSTs

BSTs are used everywhere:

  • Phone Books: Names in alphabetical order
  • Dictionaries: Words in alphabetical order
  • File Systems: Files organized by name
  • Databases: Fast data lookup and sorting
  • Auto-complete: Quick word suggestions
  • Spell Check: Fast word validation

BST vs Regular Arrays

OperationArrayBST (Balanced)
SearchO(n)O(log n)
InsertO(n)O(log n)
DeleteO(n)O(log n)
Sorted?MaybeAlways!

Practice Time!

Exercise 1: Student Grade Organizer

Create a BST to store student grades:

  • Add students with their grades
  • Find a student’s grade quickly
  • List all students in grade order

Exercise 2: Library Book Catalog

Build a library system:

  • Books organized by title
  • Quick book lookup
  • Books in alphabetical order

Exercise 3: Price Comparison

Store product prices:

  • Find cheapest product
  • Find most expensive product
  • Find products in price range

Exercise 4: Calendar Events

Organize events by date:

  • Add events with dates
  • Find events on specific date
  • List events in chronological order

Exercise 5: Music Playlist

Create a music library:

  • Songs organized by title
  • Quick song search
  • Alphabetical song list

What’s Next?

Excellent! You now understand Binary Search Trees. Next, we’ll learn about Sorting Algorithms - different ways to arrange data in order!

Quick Quiz

  1. What’s the main rule of a Binary Search Tree?
  2. Why are BSTs faster than regular lists for searching?
  3. What order do you get when traversing a BST in-order?
  4. Where would you put a smaller number in a BST?
  5. Name three real-life examples of BSTs.

Remember: BSTs are like phone books - everything stays perfectly organized for super-fast lookup!