2. Binary Search Tree
This data structure is a bit more interesting. With this data structure it's easy to implement a set data type, which is a collection of unique elements. It's also easy to implement operations such as search, finding min or max element in the set and search of previous and next values. All those operations take O(logn) time if the tree is balanced.
Figure 2.1

On the Figure 2.1 you can see a balanced tree on the left and an unbalanced tree on the right. If the tree is balanced, the operations mentioned above will take Ø(lgn) where Ø - theta. If the tree is unbalanced, the operations will take O(lgn).
Binary Search Tree (BST) is a node-based binary tree data structure which has the following properties:
- The left subtree of a node contains only nodes with values smaller than the node's value.
- The right subtree of a node contains only nodes with values bigger than the node's value.
- The left and right subtree each must also be a binary search tree or be
null.
If a node is to be inserted into a tree, it is compared with current node (starting from the root). If the node's value is less than current, we send it down to left subtree. If node's value is greater than or equal to current - it is sent to the right subtree. This process is repeated for each encountered node.
2.1 Tree Walks​
The binary search tree property allows us to print out all the values in a binary search tree in sorted order by a simple recursive algorithm, called an inorder tree walk. This algorithm is named so because it prints the value of the root of a subtree between printing the values in its left subtree and printing those in its right subtree. (Similarly, a preorder tree walk prints the root before the values in either subtree, and a postorder tree walk prints the root after the values in its subtrees.)
Listing 2.1 - Binary Tree Traversal
Figure 2.2

For example, with a tree in Figure 2.2, those tree walks would give following results:
- Inorder (Left, Root, Right):
35691112 - Preorder (Root, Left, Right):
95361211 - Postorder (Left, Right, Root):
53612119
info
The recursive approach is used to implement the Binary Tree Traversal. Check out here the advantages and disadvantages of using recursion. Feel free to figure out on your own how to implement the same using iterative approach.
2.2 Searching​
Because of the BST properties, it's very easy to search for an element with a following function:
Listing 2.2 - searchTree
We can always find an element in a binary search tree whose value is a minimum by following left child pointers from the root until we encounter a null. The search of a tree's maximum is a symmetric procedure:
Listing 2.3 - treeMinimum and treeMaximum
Given a node in a binary search tree, sometimes we need to find its successor in the sorted order determined by an inorder tree walk. If all values are distinct, the successor of a node node is the node with the smallest value greater than node.value. The strategy has three basic cases:
- in case
treeandnodeare the same thenullshould be returned - in that case
nodehas a right subtree we need to find the left most node in its right subtree which is also the lowest node in its right subtree - in that case
nodedoes not have a right subtree we need to walk down thetreenode until we match thenodeand return its parent
Listing 2.4 - getSuccessor
For an example for Figure 2.2 the inorder successor of 6 is 9, the inorder successor of 5 is 6 and inorder successor of 3 is 5.
2.3 Insert​
To insert a new value value into a binary search tree tree, we use the function insertNode. It takes a node node for which: node.value = value, node.left = null, and node.right = null and inserts it into an appropriate position in the tree.
Listing 2.5 - insertNode
In the Figure 2.2, we want to insert 7. We look at 9 and go left, we look at 5 and go right for 6 and insert 7 into its right subtree.
2.4 Deletion​
The overall strategy for deleting a node node from a binary search tree tree has three basic cases but, as we shall see, one of the cases is a bit tricky:
- If
nodeis leaf (has no children), then we simply remove it by modifying its parent to replacenodewithnullas its child. - If
nodehas just one child, then we elevate that child to takenodes position in the tree by modifyingnodeparent to replacenodebynodes child. - If
nodehas two children, then we findnodesuccessorparent— which must be innoderight subtree — and haveparenttakenodes position in the tree. The rest ofnodes original right subtree becomesparents new right subtree, andnodes left subtree becomesparents new left subtree. This case is the tricky one because, as we shall see, it matters whetherparentisnodes right child.
Figure 2.3

In the Figure 2.3, we are removing element 18. Since it has no children, we set the 20's left subtree to null.
Figure 2.4

In the second case we are removing element 25. Since it has only one child - 30, we replace the 20's right subtree with 30.
Figure 2.5

In the third case, we are removing element 20. Node 20 has 2 children. To delete the node we need to find its inorder successor or inorder predecessor. In our example the inorder successor is node 30 and inorder predecessor is node 19. The inorder successor will be the minimum of the right subtree. The inorder predecessor is going to be the maximum of the left subtree. After replacing the node with found value, we must delete the replacing node.
Listing 2.6 - deleteNode
The worst-case time complexity of search, insert, and delete operations is O(h) where h is the height of the Binary Search Tree. In the worst case, we may have to travel from root to the deepest leaf node. The height of a skewed tree may become n (number of nodes), and the time complexity of search and insert operation may become O(n).