The three mutating operations on a Binary Search Tree — insert, search, and delete — each exploit the ordering invariant to navigate the tree without examining every node. On a balanced tree ofDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/tutosrive/ed/llms.txt
Use this file to discover all available pages before exploring further.
n nodes, all three run in O(log n) average time because each comparison eliminates roughly half of the remaining nodes. In the worst case (a fully degenerate tree), performance degrades to O(n). Understanding how these operations maintain the BST property is essential before moving on to self-balancing variants.
Insert
Insertion walks from the root toward a leaf, turning left when the new value is smaller than the current node and right when it is greater or equal. When it reaches an empty child slot, it places the new node there and sets up the parent back-pointer.insert and _insert methods
insertcreates theNodeand delegates to_insertunless the tree is empty (in which case the new node becomes the root directly)._insertis recursive. At each level it comparesnew_node.valuewithcurrent_node.valueand descends left or right accordingly.- When an empty slot (
None) is found, the node is attached andnew_node.parentis set to the current node — keeping the back-pointer accurate.
Inserting a value
Search
Search uses the same left-or-right navigation as insert, but instead of adding a node it looks for an existing value. It returns the matchingNode object, or None if the value is not present.
search and _search methods
current_node is None is reached when the target value is not in the tree — the search has fallen off the bottom without finding a match. The other base case current_node.value == value returns the found node immediately.
Example:
Searching for a value
Delete
Deletion is the most complex BST operation because removing a node must preserve the ordering invariant for every node in the tree. There are exactly three structural cases depending on how many children the target node has.Case 1 — Leaf node (no children)
A leaf node can be removed by simply detaching it from its parent. The helper Example: Deleting
changeNodePosition is called with None as the replacement, which clears the parent’s child pointer.Deleting a leaf node
20 from [50, 30, 70, 20, 40] — node 20 has no children, so 30.left is set to None.Case 2 — Node with two children
When the target has both a left and a right child, a direct removal would leave two orphaned subtrees. The solution is to find the inorder predecessor — the largest value in the left subtree — and promote it into the deleted node’s position. This preserves the BST ordering because the predecessor is, by definition, larger than everything else in the left subtree and smaller than everything in the right subtree.The extra
Deleting a node with two children
if predecessor.parent != node_to_delete guard handles the sub-case where the predecessor is the direct left child of the deleted node (i.e., the left child has no right subtree). In that case, the predecessor does not need to be detached from its current position before being linked in.Supporting Methods
The three cases above rely on two helpers:_getPredecessor (finds the largest node in the left subtree) and changeNodePosition (rewires parent/child pointers atomically).
_getPredecessor — finds the inorder predecessor
changeNodePosition — replaces one subtree with another
Full delete and _delete methods
Public delete entry point and internal _delete dispatcher