什么是二叉查找树
二叉查找树本质就是通过二分搜索的方法来快速查找
二叉查找树也叫二叉搜索树或是二叉排序树,它具有一定的规则:
- 左子树中所有结点的值,均小于其根结点的值。
- 右子树中所有结点的值,均大于其根结点的值。
- 二叉搜索树的子树也是二叉搜索树。
一棵二叉搜索树长这样:

查找值为15的结点:
- 从根结点18开始,因为15小于18,所以从左边开始找。
- 接着来到10,发现10比15小,所以继续往右边走。
- 来到15,成功找到。
实际上,我们在对普通二叉树进行搜索时,可能需要挨个进行查看比较,而有了二叉搜索树,查找效率就大大提升了,它就像我们前面的二分搜索那样。
因为二叉搜索树要求比较严格,所以我们在插入结点时需要遵循一些规律,这里我们来尝试编写一下:
1 |
|
二叉查找树的操作
插入操作
我们就以上面这颗二叉查找树为例,现在我们想要依次插入这些结点,我们需要编写一个特殊的插入操作,这里需要注意一下,二叉查找树不能插入重复元素,如果出现重复直接忽略:
1 | Node insert(Node root, E element){ |
上诉代码的主要图形逻辑是,根据插入逻辑找到一个空节点,然后插入元素。
这样我们就可以通过不断插入创建一棵二叉查找树了:
1 | void inOrder(Node root){ |
1 | int main() { |
可以看到中序结果为:

搜索操作
那么插入写好之后,我们怎么找到对应的结点呢?实际上也是按照规律来就行了:
1 | Node find(Node root, E target){ |
删除操作
最后我们来看看二叉查找树的删除操作,这个操作就比较麻烦了,因为可能会出现下面的几种情况:
- 要删除的结点是叶子结点。
- 要删除的结点是只有一个孩子结点。
- 要删除的结点有两个孩子结点。
首先我们来看第一种情况,这种情况实际上最好办,直接删除就完事了:

而第二种情况,就有点麻烦了,因为有一个孩子,当移除后,需要将孩子结点连接上去:

可以看到在调整后,依然满足二叉查找树的性质。最后是最麻烦的有两个孩子的情况,这种该怎么办呢?前面只有一个孩子直接上位就完事,但是现在两个孩子,到底谁上位呢?这就不好办了,为了保持二叉查找树的性质,现在有两种选择:
- 选取其左子树中最大结点上位
- 选择其右子树中最小结点上位
这里我们以第一种方式为例:

现在我们已经分析完三种情况了,那么我们就来编写一下代码吧:
1 | Node delete(Node root, E target){ |
说些什么吧!