Understanding Binary Search Trees — Level 2
Implementation deep dive: master BST operations including insertion, search, deletion, and tree traversals with production-ready code patterns.
Implementation deep dive: master BST operations including insertion, search, deletion, and tree traversals with production-ready code patterns.
Author
Mr. Oz
Date
Read
8 mins
Level 2
In Level 1, we understood what BSTs are. Now let's implement them. We'll cover the core operations that make BSTs useful in real applications.
Every BST node needs three things: a value and two child pointers.
# Python
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
// Java
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) { this.val = val; }
}
// C++
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
Searching is the fundamental BST operation. Compare and go left or right.
# Python
def search(root, target):
if not root or root.val == target:
return root
if target < root.val:
return search(root.left, target)
return search(root.right, target)
Time: O(log n) balanced, O(n) worst case | Space: O(log n) recursion stack
Insertion follows the same path as search, but we create a new node when we hit a null.
# Python
def insert(root, val):
if not root:
return TreeNode(val)
if val < root.val:
root.left = insert(root.left, val)
else:
root.right = insert(root.right, val)
return root
// Java
public TreeNode insert(TreeNode root, int val) {
if (root == null) return new TreeNode(val);
if (val < root.val)
root.left = insert(root.left, val);
else
root.right = insert(root.right, val);
return root;
}
Note: Equal values typically go to the right subtree (or left, depending on implementation choice). Be consistent!
Deletion has three cases based on how many children the node has:
# Python
def delete(root, key):
if not root:
return None
if key < root.val:
root.left = delete(root.left, key)
elif key > root.val:
root.right = delete(root.right, key)
else: # Found the node to delete
if not root.left:
return root.right
if not root.right:
return root.left
# Two children: find inorder successor
succ = find_min(root.right)
root.val = succ.val
root.right = delete(root.right, succ.val)
return root
# Helper: find minimum node
def find_min(node):
while node.left:
node = node.left
return node
Four main traversal patterns — each serves different purposes:
Returns sorted values in a BST!
def inorder(root):
if root:
inorder(root.left)
print(root.val)
inorder(root.right)
Useful for copying/serializing trees
def preorder(root):
if root:
print(root.val)
preorder(root.left)
preorder(root.right)
Useful for deleting/calculation trees
def postorder(root):
if root:
postorder(root.left)
postorder(root.right)
print(root.val)
Visit nodes level by level
from collections import deque
def levelorder(root):
if not root: return
q = deque([root])
while q:
node = q.popleft()
print(node.val)
if node.left: q.append(node.left)
if node.right: q.append(node.right)
| Operation | Average | Worst |
|---|---|---|
| Search | O(log n) |
O(n) |
| Insert | O(log n) |
O(n) |
| Delete | O(log n) |
O(n) |
| Traversal | O(n) |
O(n) |
Worst case occurs when the tree becomes a linked list (completely unbalanced).
Level 1
Learn the fundamentals of BSTs through an engaging magical library analogy.
Author
Mr. Oz
Duration
5 mins
Level 2
Implementation details, insertion, search, deletion, and traversal operations.
Author
Mr. Oz
Duration
8 mins
Level 3
Balancing techniques, AVL trees, Red-Black trees, and performance optimization.
Author
Mr. Oz
Duration
12 mins