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.
- High-Performance Waterproof Solar Connectors
- Durable IP68 Waterproof Solar Connectors for Outdoor Use
- High-Quality Tinned Copper Material for Durability
- High-Quality Tinned Copper Material for Long Service Life
- Y Branch Parallel Solar Connector for Enhanced Power
- 10AWG Tinned Copper Solar Battery Cables
- NEMA 5-15P to Powercon Extension Cable Overview
- Dual Port USB 3.0 Adapter for Optimal Speed
- 4-Pin XLR Connector: Reliable Audio Transmission
- 4mm Banana to 2mm Pin Connector: Your Audio Solution
- 12GB/s Mini SAS to U.2 NVMe Cable for Fast Data Transfer
- CAB-STK-E Stacking Cable: 40Gbps Performance
- High-Performance CAB-STK-E Stacking Cable Explained
- Best 10M OS2 LC to LC Fiber Patch Cable for Data Centers
- Mini SAS HD Cable: Boost Data Transfer at 12 Gbps
- Multi Rate SFP+: Enhance Your Network Speed
- Best 6.35mm to MIDI Din Cable for Clear Sound
- 15 Pin SATA Power Splitter: Solutions for Your Device Needs
- 9-Pin S-Video Cable: Enhance Your Viewing Experience
- USB 9-Pin to Standard USB 2.0 Adapter: Easy Connection
- 3 Pin to 4 Pin Fan Adapter: Optimize Your PC Cooling
- S-Video to RCA Cable: High-Definition Connections Made Easy
- 6.35mm TS Extension Cable: High-Quality Sound Solution
- BlackBerry Curve 9360: Key Features and Specs






















Leave a comment