Binary Search Tree (BST)
A Binary Search Tree (BST) is a specialized binary tree that enforces a strict ordering property to enable efficient search, insertion, and deletion operations. Unlike general binary trees, BSTs organize data such that for any node:
- All values in the left subtree are less than the node’s value.
- All values in the right subtree are greater than the node’s value.
- No duplicate values are allowed (or duplicates can be handled by modifying the property, e.g., storing counts).
This ordering property allows BSTs to achieve O(log n) average time complexity for core operations (vs. O(n) for general binary trees), making them ideal for sorted data storage and fast lookups.
I. Core Properties of BSTs
- Ordering Property: For every node
N:- Left child <
N< Right child. - This property recursively applies to all subtrees.
- Left child <
- In-order Traversal: An in-order traversal of a BST yields nodes in sorted ascending order (a defining feature of BSTs).
- Uniqueness: By default, BSTs do not allow duplicate values (duplicates can be handled by storing a count of occurrences in each node).
- Balance Impact: Performance depends on tree balance:
- Balanced BST: Height = \(O(\log n)\) (e.g., AVL Tree, Red-Black Tree) → optimal O(log n) operations.
- Skewed BST: Height = \(O(n)\) (e.g., inserting sorted data) → degrades to O(n) operations (equivalent to a linked list).
II. BST Implementation (Python)
We’ll implement a BST with core operations (insert, search, delete), traversal methods, and utility functions (find min/max, successor/predecessor).
1. TreeNode Class
python
运行
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val # Node value
self.left = left # Left child (values < val)
self.right = right # Right child (values > val)
def __str__(self):
return str(self.val)
2. BST Class (Core Operations)
python
运行
class BinarySearchTree:
def __init__(self):
self.root = None # Root of the BST
# -------------------------- Insertion --------------------------
def insert(self, val):
"""Insert a value into the BST (recursive)"""
def _insert(node, val):
# Base case: create new node if current node is None
if not node:
return TreeNode(val)
# Recurse left if val < current node's value
if val < node.val:
node.left = _insert(node.left, val)
# Recurse right if val > current node's value (no duplicates)
elif val > node.val:
node.right = _insert(node.right, val)
# Do nothing if val already exists
return node
self.root = _insert(self.root, val)
# -------------------------- Search --------------------------
def search(self, val):
"""Search for a value in the BST (recursive) → return node or None"""
def _search(node, val):
if not node or node.val == val:
return node # Return node if found, None otherwise
if val < node.val:
return _search(node.left, val)
else:
return _search(node.right, val)
return _search(self.root, val)
# -------------------------- Deletion --------------------------
def delete(self, val):
"""Delete a value from the BST (recursive) → return True if deleted, False otherwise"""
self.root, deleted = self._delete(self.root, val)
return deleted
def _delete(self, node, val):
"""Helper for delete: returns (new root of subtree, deleted flag)"""
if not node:
return node, False # Value not found
deleted = False
# Step 1: Find the node to delete
if val < node.val:
node.left, deleted = self._delete(node.left, val)
elif val > node.val:
node.right, deleted = self._delete(node.right, val)
else:
# Step 2: Node found → handle 3 cases
deleted = True
# Case 1: Node has no children (leaf node)
if not node.left and not node.right:
return None, deleted
# Case 2: Node has one child
elif not node.left: # Only right child
return node.right, deleted
elif not node.right: # Only left child
return node.left, deleted
# Case 3: Node has two children → find inorder successor (smallest in right subtree)
successor = self._find_min(node.right)
# Replace node's value with successor's value
node.val = successor.val
# Delete the successor (recursively)
node.right, _ = self._delete(node.right, successor.val)
return node, deleted
# -------------------------- Utility Functions --------------------------
def _find_min(self, node):
"""Find the smallest node in a subtree (leftmost node)"""
current = node
while current.left:
current = current.left
return current
def _find_max(self, node):
"""Find the largest node in a subtree (rightmost node)"""
current = node
while current.right:
current = current.right
return current
def find_min_val(self):
"""Find the minimum value in the BST"""
if not self.root:
return None
return self._find_min(self.root).val
def find_max_val(self):
"""Find the maximum value in the BST"""
if not self.root:
return None
return self._find_max(self.root).val
# -------------------------- Traversals --------------------------
def in_order(self, node=None, traversal=None):
"""In-order traversal (Left → Visit → Right) → sorted order"""
if node is None:
node = self.root
if traversal is None:
traversal = []
if node:
self.in_order(node.left, traversal)
traversal.append(node.val)
self.in_order(node.right, traversal)
return traversal
def pre_order(self, node=None, traversal=None):
"""Pre-order traversal (Visit → Left → Right)"""
if node is None:
node = self.root
if traversal is None:
traversal = []
if node:
traversal.append(node.val)
self.pre_order(node.left, traversal)
self.pre_order(node.right, traversal)
return traversal
def post_order(self, node=None, traversal=None):
"""Post-order traversal (Left → Right → Visit)"""
if node is None:
node = self.root
if traversal is None:
traversal = []
if node:
self.post_order(node.left, traversal)
self.post_order(node.right, traversal)
traversal.append(node.val)
return traversal
def level_order(self):
"""Level-order traversal (BFS)"""
if not self.root:
return []
traversal = []
queue = [self.root]
while queue:
current = queue.pop(0)
traversal.append(current.val)
if current.left:
queue.append(current.left)
if current.right:
queue.append(current.right)
return traversal
3. Test the BST
python
运行
if __name__ == "__main__":
bst = BinarySearchTree()
# Insert values
values = [50, 30, 70, 20, 40, 60, 80]
for val in values:
bst.insert(val)
# Traversals
print("In-order Traversal (sorted):", bst.in_order()) # Output: [20, 30, 40, 50, 60, 70, 80]
print("Pre-order Traversal:", bst.pre_order()) # Output: [50, 30, 20, 40, 70, 60, 80]
print("Post-order Traversal:", bst.post_order()) # Output: [20, 40, 30, 60, 80, 70, 50]
print("Level-order Traversal:", bst.level_order()) # Output: [50, 30, 70, 20, 40, 60, 80]
# Search
print("\nSearch for 40:", bst.search(40).val if bst.search(40) else "Not found") # Output: 40
print("Search for 90:", bst.search(90).val if bst.search(90) else "Not found") # Output: Not found
# Min/Max Values
print("\nMinimum Value:", bst.find_min_val()) # Output: 20
print("Maximum Value:", bst.find_max_val()) # Output: 80
# Deletion
bst.delete(30) # Delete node with one child (30 has left=20, right=40 → two children)
print("\nIn-order after deleting 30:", bst.in_order()) # Output: [20, 40, 50, 60, 70, 80]
bst.delete(70) # Delete node with one child (70 has left=60, right=80 → two children)
print("In-order after deleting 70:", bst.in_order()) # Output: [20, 40, 50, 60, 80]
bst.delete(50) # Delete root node (has two children)
print("In-order after deleting 50:", bst.in_order()) # Output: [20, 40, 60, 80]
III. Key Operations Explained
1. Insertion
- Recursive Approach: Traverse the tree to find the correct position (left if value < current node, right if value > current node).
- Duplicate Handling: Ignores duplicates (modify to store counts if duplicates are allowed).
- Time Complexity: O(log n) for balanced BSTs, O(n) for skewed BSTs.
2. Search
- Recursive Approach: Traverse left/right based on value comparison. Returns the node if found,
Noneotherwise. - Critical Feature: Leverages the BST ordering property to avoid checking all nodes (faster than linear search for sorted data).
- Time Complexity: O(log n) (balanced), O(n) (skewed).
3. Deletion (Most Complex Operation)
Deletion requires handling three cases to preserve the BST property:
- Case 1: Leaf Node (No Children): Simply remove the node (set parent’s pointer to
None). - Case 2: Node with One Child: Replace the node with its child (bypass the node).
- Case 3: Node with Two Children:
- Find the inorder successor (smallest node in the right subtree) — this preserves the BST property (successor is larger than all left subtree nodes and smaller than all right subtree nodes).
- Replace the node’s value with the successor’s value.
- Delete the successor (recursively, which falls into Case 1 or 2).
4. Utility Functions
- Find Min/Max: The minimum value is the leftmost node; the maximum is the rightmost node (O(log n) time).
- Traversals: In-order traversal is the most useful for BSTs, as it returns sorted values.
IV. Time & Space Complexity
| Operation | Average Time Complexity | Worst-Case Time Complexity | Space Complexity | Explanation |
|---|---|---|---|---|
| Insertion | O(log n) | O(n) | O(log n) | – Average: Balanced tree (height = log n, recursive call stack).- Worst: Skewed tree (height = n, call stack = O(n)). |
| Search | O(log n) | O(n) | O(log n) | Same as insertion (traverses a single path from root to leaf). |
| Deletion | O(log n) | O(n) | O(log n) | Finding the node and successor takes O(log n) in average case. |
| Traversal (In-order/Pre-order/Post-order) | O(n) | O(n) | O(log n) (recursive) / O(n) (iterative) | Visits all nodes (O(n) time); space depends on call stack or auxiliary data structures. |
| Find Min/Max | O(log n) | O(n) | O(1) (iterative) / O(log n) (recursive) | Traverses a single path to leftmost/rightmost node. |
V. BST Limitations & Balanced Alternatives
The main limitation of a standard BST is its sensitivity to insertion order:
- Inserting sorted data (e.g., 1, 2, 3, 4) creates a right-skewed BST (height = n), reducing all operations to O(n) time.
- To solve this, balanced BSTs automatically maintain a low height (O(log n)) by rebalancing the tree after insertions/deletions. Common balanced BSTs include:
| Balanced BST Type | Description |
|---|---|
| AVL Tree | Maintains a balance factor (difference between left and right subtree heights) of ±1. Rebalances via rotations (left, right, left-right, right-left). |
| Red-Black Tree | Uses color rules (nodes are red or black) to ensure the longest path from root to leaf is at most twice the shortest path. Used in Java TreeMap, C++ map. |
| Splay Tree | Self-adjusting BST that moves frequently accessed nodes closer to the root (improves average-case performance for repeated accesses). |
VI. Practical Applications of BSTs
- Sorted Data Storage: In-order traversal provides sorted data (no need for extra sorting).
- Database Indexing: Balanced BSTs (e.g., Red-Black Trees) are used to index database tables, enabling fast range queries and lookups.
- Autocomplete Systems: BSTs can store words and support prefix searches (e.g., typing “app” returns “apple”, “application”).
- Priority Queues: Modified BSTs (e.g., treaps) combine BST and heap properties for efficient priority-based operations.
- Binary Search Optimization: BSTs are the foundation of binary search, used in algorithms for finding elements in sorted arrays/lists.
Summary
Practical applications include sorted storage, database indexing, autocomplete, and priority queues.
A Binary Search Tree (BST) is a binary tree with a strict ordering property: left subtree values < node value < right subtree values.
Core operations (insert, search, delete) have O(log n) average time complexity (O(n) worst-case for skewed trees).
In-order traversal of a BST yields nodes in sorted order — a key feature for sorted data applications.
Deletion requires handling three cases (leaf, one child, two children) and uses the inorder successor to preserve the BST property.
Standard BSTs are limited by skewing; balanced BSTs (AVL, Red-Black) solve this by maintaining O(log n) height.
- iPhone 15 Pro Review: Ultimate Features and Specs
- iPhone 15 Pro Max: Key Features and Specifications
- iPhone 16: Features, Specs, and Innovations
- iPhone 16 Plus: Key Features & Specs
- iPhone 16 Pro: Premium Features & Specs Explained
- iPhone 16 Pro Max: Features & Innovations Explained
- iPhone 17 Pro: Features and Innovations Explained
- iPhone 17 Review: Features, Specs, and Innovations
- iPhone Air Concept: Mid-Range Power & Portability
- iPhone 13 Pro Max Review: Features, Specs & Performance
- iPhone SE Review: Budget Performance Unpacked
- iPhone 14 Review: Key Features and Upgrades
- Apple iPhone 14 Plus: The Ultimate Mid-range 5G Smartphone
- iPhone 14 Pro: Key Features and Innovations Explained
- Why the iPhone 14 Pro Max Redefines Smartphone Technology
- iPhone 15 Review: Key Features and Specs
- iPhone 15 Plus: Key Features and Specs Explained
- iPhone 12 Mini Review: Compact Powerhouse Unleashed
- iPhone 12: Key Features and Specs Unveiled
- iPhone 12 Pro: Premium Features and 5G Connectivity
- Why the iPhone 12 Pro Max is a Top Choice in 2023
- iPhone 13 Mini: Compact Powerhouse in Your Hand
- iPhone 13: Key Features and Specs Overview
- iPhone 13 Pro Review: Features and Specifications






















Leave a comment