There are no items in your cart
Add More
Add More
| Item Details | Price | ||
|---|---|---|---|
A comprehensive guide to understanding and implementing Binary Search Trees in Python
January 12, 2025
"A Binary Search Tree represents a powerful data structure that combines the efficiency of binary search with the flexibility of a linked structure."
A Binary Search Tree (BST) is a special type of binary tree where each node follows specific ordering properties. The left subtree of any node contains only values less than the node's value, while the right subtree contains only values greater than the node's value. This property must be maintained throughout the entire tree.
• All nodes in the left subtree have values less than the current node
• All nodes in the right subtree have values greater than the current node
• Both left and right subtrees must also be binary search trees
• The tree structure provides an average time complexity of O(log n) for operations
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.value = key
class BST:
def __init__(self):
self.root = None
def insert(self, root, key):
if root is None:
return Node(key)
if key < root.value:
root.left = self.insert(root.left, key)
else:
root.right = self.insert(root.right, key)
return root
def insert_value(self, key):
if not self.root:
self.root = Node(key)
else:
self.insert(self.root, key)
BSTs can be traversed in three main ways:
# Pre-order Traversal
def pre_order_traversal(root):
if root:
print(root.value, end=" ")
pre_order_traversal(root.left)
pre_order_traversal(root.right)
# In-order Traversal
def in_order_traversal(root):
if root:
in_order_traversal(root.left)
print(root.value, end=" ")
in_order_traversal(root.right)
# Post-order Traversal
def post_order_traversal(root):
if root:
post_order_traversal(root.left)
post_order_traversal(root.right)
print(root.value, end=" ")
Let's explore the complete implementation of a Binary Search Tree with insertion and deletion operations. This implementation handles all cases of deletion and provides a clean, reusable interface.
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.value = key
class BST:
def __init__(self):
self.root = None
def insert(self, value):
"""Insert a new value into the BST"""
if not self.root:
self.root = Node(value)
else:
self._insert_recursive(self.root, value)
def _insert_recursive(self, node, value):
"""Helper method for insertion"""
if value < node.value:
if node.left is None:
node.left = Node(value)
else:
self._insert_recursive(node.left, value)
else:
if node.right is None:
node.right = Node(value)
else:
self._insert_recursive(node.right, value)
def delete(self, value):
"""Delete a value from the BST"""
self.root = self._delete_recursive(self.root, value)
def _delete_recursive(self, node, value):
"""Helper method for deletion"""
# Base case: if node is None, tree is empty
if node is None:
return node
# Recursively find the node to delete
if value < node.value:
node.left = self._delete_recursive(node.left, value)
elif value > node.value:
node.right = self._delete_recursive(node.right, value)
else:
# Node found! Handle the three deletion cases
# Case 1: Leaf node (no children)
if node.left is None and node.right is None:
return None
# Case 2: Node with one child
if node.left is None:
return node.right
if node.right is None:
return node.left
# Case 3: Node with two children
# Find the inorder successor (smallest value in right subtree)
successor = self._find_min(node.right)
# Copy successor value to current node
node.value = successor.value
# Delete the successor
node.right = self._delete_recursive(node.right, successor.value)
return node
def _find_min(self, node):
"""Helper method to find the minimum value node in a subtree"""
current = node
while current.left is not None:
current = current.left
return current
The delete operation handles three cases:
# Create a BST and insert values
bst = BST()
values = [50, 30, 20, 40, 70, 60, 80]
for value in values:
bst.insert(value)
# Delete operations
bst.delete(20) # Deleting leaf node
bst.delete(30) # Deleting node with one child
bst.delete(70) # Deleting node with two children
When deleting a node from a BST, we need to handle three distinct cases:
Time Complexity:
Here's how you can use this implementation:
# Create a new BST
bst = BST()
# Insert some values
values = [50, 30, 20, 40, 70, 60, 80]
for value in values:
bst.insert(value)
# Delete a leaf node
bst.delete(20)
# Delete a node with one child
bst.delete(30)
# Delete a node with two children
bst.delete(70)
Learn how to prepare for data science interviews with real questions, no shortcuts or fake promises.
See What’s Inside