Collections of Binary Search Operations
Translator: Fulin Li
Author:labuladong
In the previous article about framework thinking, we introduced the traverse framework of the binary tree. There should be a deep impression of this framework left in your mind. In this article, we will put the framework into practice and illustrate how does it flexible resolve all issues about the binary tree.
The basic idea of binary tree algorithm design: Defining the manipulation in the current node and the last things are thrown to the framework.
There are two simple examples to illustrate such an idea, and you can warm up first.
1. How to add an integer to every node of binary tree?
2. How to determine whether two binary trees are identical?
It is straightforward to understand the two above examples with the help of the traverse framework of the binary tree. If you can understand it, now you can handle all the problems with the binary tree.
Binary Search Tree (BST), is a common type of binary. The tree additionally satisfies the binary search property, which states that the key in each node must be greater than or equal to any key stored in the left sub-tree, and less than or equal to any key stored in the right sub-tree.
An example corresponding to the definition is shown as:
Next, we will realize basic operations with BST, including compliance checking of BST, addition, deletion, and search. The process of deletion and compliance checking may be slightly more complicated.
0. Compliance checking of BST
This operation sometimes is error-prone. Following the framework mentioned above, the manipulation of every node in the binary tree is to compare the key in the left child with the right child, and it seems that the codes should be written like this:
But such algorithm is an error. Because the key in each node must be greater than or equal to any key stored in the left sub-tree, and less than or equal to any key stored in the right sub-tree. For example, the following binary tree is not a BST, but our algorithm will make the wrong decision.
Don't panic though the algorithm is wrong. Our framework is still correct, and we didn't notice some details information. Let's refresh the definition of BST: The manipulations in root node should not only include the comparison between left and right child, but it also require a comparison of the whole left and right sub-tree. What should do? It is beyond the reach of the root node.
In this situation, we can use an auxiliary function to add parameters in the parameter list, which can carry out more useful information. The correct algorithm is as follows:
1. Lookup function in BST
According to the framework, we can write the codes like this:
It is entirely right. If you can write like this, you have remembered the framework. Now you can attempt to take some details into account: How to leverage the property of BST to facilitate us to search efficiently.
It is effortless! We don't have to search both of nodes recursively. Similar to the binary search, we can exclude the impossible child node by comparing the target value and root value. We can modify the codes slightly:
Therefore, we can modify the original framework to abstract a new framework for traversing BST.
3. Deletion function in BST
This problem is slightly complicated. But you can handle it with the help of the framework! Similar to the insert function, we should find it before modification. Let's write it first:
When you find the target, for example, node A. It isn't effortless for us to delete it. Because we can't destroy the property of BST when we realize the Deletion function. There are three situations, and we will illustrate in the following three pictures:
Case 1: Node A is just the leaf node, and it's child nodes are all null. In this way, we can delete it directly.
The picture is excerpted from LeetCode
Case 2: The node A has only one child node, then we can change its child node to replace its place.
The picture is excerpted from LeetCode
Case 3: Node A has two child nodes. To avoid destroying the property of BST, node A must find the maximum node in left sub-tree or the minimum node in the right sub-tree to replace its place. We use the minimum node in the right sub-tree to illustrate it.
The picture is excerpted from LeetCode
The three situations are analyzed, and we can fill them into the framework and simplify the codes:
In this way, we can finish the deletion function. Note that such an algorithm is not perfect because we wouldn't exchange the two nodes by 'root.val = minNode.val'. Generally, we will exchange the root and minNode by a series of slightly complicated linked list operations. Because the value of Val may be tremendous in the specific application, it's time-consuming to modify the value of the node. Still, the linked list operations only require to change the pointer and don't modify values.
Summary
In this article, you can learn the following skills:
The basic idea of designing a binary tree algorithm: Defining the manipulations in the current node and the last things are thrown to the framework.
If the manipulations in the current node have influence in its sub-tree, we can add additional parameters to the parameter list by adding auxiliary function.
On the foundation of the framework of the binary tree, we abstract the traverse framework of BST:
We grasp the basic operations of BST.
Last updated