Binary search tree’s or BST, have to have an important property which is the BST property. This means that each node should be strictly greater than the nodes to the left of it and should be greater than or equal to the nodes to the right of it.
The main methods that can performed on a BST is Insertion, Searching, and Deletion. Deletion is a bit more difficult to implement relative to insertion and searching due to possible edge cases
To perform a deletion on a single children node the process is simple, delete the node and shift any child nodes if applicable. However, when dealing with nodes with two children we use Inorder Predecessor and Inorder Sucessor. Inorder Predecessor is the largest node (rightmost) in the left subtree of the node you want to delete. Inorder Successor is the smallest node (leftmost) in the right subtree of the node you want to delete. This process is good for root nodes and nodes with two children.
The average case time complexity is O(log(n) because we are splitting our traversal by half through every node we pass, since we decide we’re continuing towards the left or right subtree. However, there are cases where we iterate through the whole tree. For instance, in a single linked linear tree, we would have to iterate through the whole tree in the worst case.
The space complexity can vary depending on the algorithm. For instance, for a recursive algorithm we would use on average O(log(N)) and in the worst caseO(N) space, since we are using frames on a call stack and this worst case scenario. Now, when solved iteratively the space efficiency is much better. For iterative solution we use a worst case of O(1). This is because we are not storing frames on a call stack.
Example:
Approach 1:
The insert, and contains method work the same. First, find the target node by using the fact that we traverse left or right based on if value > | < currentNode.value. If it is less then, then we traverse left and conversely if greater than. The remove method is a bit more complicated and requires solving for multiple edge cases such as two children nodes, single children noes, and nodes with no children. In any case, we first traverse through the BST and find the target node while also keeping track of the parent node by constantly setting it for each iteration. Once we’ve found the node we can use reassignment to ensure