Last active
July 31, 2025 05:42
-
-
Save ascherj/21152c800d892da8a8d5a7a1971df8f5 to your computer and use it in GitHub Desktop.
Binary Search Tree - Node Insertion & Removal Demonstration
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class TreeNode: | |
| """ | |
| A node in a Binary Search Tree. | |
| Attributes: | |
| val: The value stored in the node | |
| left: Reference to the left child node | |
| right: Reference to the right child node | |
| """ | |
| def __init__(self, val: int) -> None: | |
| """ | |
| Initialize a new tree node. | |
| Args: | |
| val: The value to store in the node | |
| """ | |
| self.val = val | |
| self.left: TreeNode | None = None | |
| self.right: TreeNode | None = None | |
| def insert(root: TreeNode | None, val: int) -> TreeNode: | |
| """ | |
| Insert a new node into the BST and return the root. | |
| Args: | |
| root: The root node of the BST (can be None for empty tree) | |
| val: The value to insert | |
| Returns: | |
| TreeNode: The root node of the BST after insertion | |
| Time Complexity: O(log n) average, O(n) worst case (unbalanced tree) | |
| Space Complexity: O(log n) average, O(n) worst case (recursion stack) | |
| """ | |
| if not root: | |
| return TreeNode(val) | |
| if val > root.val: | |
| root.right = insert(root.right, val) | |
| elif val < root.val: | |
| root.left = insert(root.left, val) | |
| return root | |
| def minValueNode(root: TreeNode | None) -> TreeNode | None: | |
| """ | |
| Find and return the node with the minimum value in the BST. | |
| Args: | |
| root: The root node of the BST or subtree | |
| Returns: | |
| TreeNode: The node containing the minimum value, or None if tree is empty | |
| Time Complexity: O(log n) average, O(n) worst case (unbalanced tree) | |
| Space Complexity: O(1) - iterative approach uses constant space | |
| """ | |
| curr = root | |
| while curr and curr.left: | |
| curr = curr.left | |
| return curr | |
| def remove(root: TreeNode | None, val: int) -> TreeNode | None: | |
| """ | |
| Remove a node with the given value from the BST and return the root. | |
| Handles three deletion cases: | |
| 1. Node with no children (leaf node) | |
| 2. Node with one child | |
| 3. Node with two children (uses inorder successor) | |
| Args: | |
| root: The root node of the BST (can be None for empty tree) | |
| val: The value to remove from the BST | |
| Returns: | |
| TreeNode: The root node of the BST after removal, or None if tree becomes empty | |
| Time Complexity: O(log n) average, O(n) worst case (unbalanced tree) | |
| Space Complexity: O(log n) average, O(n) worst case (recursion stack) | |
| """ | |
| if not root: | |
| return None | |
| if val > root.val: | |
| root.right = remove(root.right, val) | |
| elif val < root.val: | |
| root.left = remove(root.left, val) | |
| else: | |
| # Node to be deleted found - handle 3 cases: | |
| # Case 1: Node has no left child (0 or 1 child on right) | |
| if not root.left: | |
| return root.right | |
| # Case 2: Node has left child but no right child (1 child on left) | |
| elif not root.right: | |
| return root.left | |
| # Case 3: Node has both left and right children | |
| else: | |
| # Find the inorder successor (smallest value in right subtree) | |
| minNode = minValueNode(root.right) | |
| # Replace current node's value with successor's value | |
| root.val = minNode.val | |
| # Delete the successor from right subtree | |
| root.right = remove(root.right, minNode.val) | |
| return root | |
| def print_tree(root: TreeNode | None, prefix: str = "", is_last: bool = True, is_root: bool = True) -> None: | |
| """ | |
| Print a visual representation of the BST using ASCII art. | |
| Args: | |
| root: The root node of the tree or subtree to print | |
| prefix: String prefix for indentation (used internally for recursion) | |
| is_last: Whether this node is the last child (used internally for recursion) | |
| is_root: Whether this is the root node (used internally for recursion) | |
| Time Complexity: O(n) - visits each node once | |
| Space Complexity: O(h) where h is height (recursion stack) | |
| """ | |
| if not root: | |
| return | |
| if is_root: | |
| print(f"{root.val}") | |
| else: | |
| connector = "└── " if is_last else "├── " | |
| print(prefix + connector + str(root.val)) | |
| children = [] | |
| if root.right: | |
| children.append((root.right, False)) | |
| if root.left: | |
| children.append((root.left, True)) | |
| for i, (child, is_left) in enumerate(children): | |
| is_last_child = (i == len(children) - 1) | |
| if is_root: | |
| extension = " " | |
| else: | |
| extension = "│ " if not is_last else " " | |
| print_tree(child, prefix + extension, is_last_child, False) | |
| def inorder_traversal(root: TreeNode | None) -> list[int]: | |
| """ | |
| Perform an inorder traversal of the BST. | |
| Inorder traversal visits nodes in ascending order for a BST: | |
| left subtree -> current node -> right subtree | |
| Args: | |
| root: The root node of the BST | |
| Returns: | |
| list: A list of values in ascending order | |
| Time Complexity: O(n) - visits each node exactly once | |
| Space Complexity: O(n) for result list + O(h) for recursion stack | |
| """ | |
| result = [] | |
| def inorder(node): | |
| if node: | |
| inorder(node.left) | |
| result.append(node.val) | |
| inorder(node.right) | |
| inorder(root) | |
| return result | |
| if __name__ == "__main__": | |
| print("=== BST INSERTION AND DELETION DEMONSTRATION ===\n") | |
| # Initialize empty BST | |
| root = None | |
| # INSERTION DEMONSTRATION | |
| print("1. BST INSERTION:") | |
| print("Building BST by inserting values: 50, 30, 20, 40, 70, 60, 80") | |
| values = [50, 30, 20, 40, 70, 60, 80] | |
| for val in values: | |
| root = insert(root, val) | |
| print(f"After inserting {val}:") | |
| print_tree(root) | |
| print(f"Inorder traversal: {inorder_traversal(root)}") | |
| print() | |
| print("=" * 50) | |
| # DELETION DEMONSTRATIONS | |
| print("\n2. BST DELETION - THREE CASES:") | |
| # Case 1: Deleting leaf node (no children) | |
| print("\nCASE 1: Deleting leaf node (no children)") | |
| print("Deleting 20 (leaf node):") | |
| print("Before deletion:") | |
| print_tree(root) | |
| print(f"Inorder: {inorder_traversal(root)}") | |
| root = remove(root, 20) | |
| print("After deleting 20:") | |
| print_tree(root) | |
| print(f"Inorder: {inorder_traversal(root)}") | |
| # Case 2: Deleting node with one child | |
| print("\n" + "=" * 30) | |
| print("\nCASE 2: Deleting node with one child") | |
| print("\nDeleting 30 (has only right child 40):") | |
| print("Before deletion:") | |
| print_tree(root) | |
| print(f"Inorder: {inorder_traversal(root)}") | |
| root = remove(root, 30) | |
| print("After deleting 30:") | |
| print_tree(root) | |
| print(f"Inorder: {inorder_traversal(root)}") | |
| # Case 3: Deleting node with two children | |
| print("\n" + "=" * 30) | |
| print("\nCASE 3: Deleting node with two children") | |
| print("Deleting 50 (root node with both left and right children):") | |
| print("Before deletion:") | |
| print_tree(root) | |
| print(f"Inorder: {inorder_traversal(root)}") | |
| root = remove(root, 50) | |
| print("After deleting 50 (replaced with inorder successor 60):") | |
| print_tree(root) | |
| print(f"Inorder: {inorder_traversal(root)}") | |
| print("\n" + "=" * 50) | |
| print("\nFINAL BST STATE:") | |
| print_tree(root) | |
| print(f"Final inorder traversal: {inorder_traversal(root)}") | |
| # Additional deletions to show more cases | |
| print("\n" + "=" * 30) | |
| print("\nADDITIONAL DELETION EXAMPLES:") | |
| print("\nDeleting 70 (has only left child 80):") | |
| root = remove(root, 70) | |
| print_tree(root) | |
| print(f"Inorder: {inorder_traversal(root)}") | |
| print("\nDeleting 40 (leaf node):") | |
| root = remove(root, 40) | |
| print_tree(root) | |
| print(f"Final inorder: {inorder_traversal(root)}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment