二叉查找树(Binary Search Tree)是一种特殊的二叉树,通常应用于动态数据的查找。
二叉查找树具有以下特性:
- 若左子树不为空,则左子树的值小于它的根节点的值;
- 若右子树不为空,则右子树的值大于它的根节点的值;
- 任意节点的左右子树均为二叉查找树;
- 没有键值相等的节点。
二叉查找树的表示
由BST特性可知,BST是一个递归的数据结构,且中序遍历BST,可以得到一个递增的有序序列。
BST的节点定义如下:
|
|
二叉查找树(BSTree)定义如下:
|
|
二叉查找树的插入
二叉查找树插入的基本思路为:若二叉查找树为空,则直接插入,若不为空,则关键值小于根节点的插入至其左子树中,关键值大于根节点的插入至其右子树中。
|
|
|
|
二叉查找树的查找
二叉查找树除了Search(查找)操作外,通常还支持Minimun(最小值)、Maximum(最大值)、Predecessor(前驱)、Successor(后继)等操作。
1. Search(查找)
从根节点开始,若二叉树非空,给定值与根节点的值比较,若不相等,则根据左小右大原则继续查找。
|
|
递归实现如下:
|
|
非递归实现如下:
|
|
2. Minimun(最小值)
根据二叉查找树的规则,树中最小值应当位于最左的节点,且该节点不能有左子树,代码如下:
|
|
3. Maximum(最大值)
根据二叉查找树的规则,树中最小值应当位于最右的节点,且该节点不能有右子树。
|
|
4. Predecessor(前驱)
找结点(x)的前驱结点。即,查找”二叉树中数据值小于该结点”的”最大结点”。
找到某个节点的前驱节点,返回为前驱或者Null。存在两种情况:
- 若节点x的左子树非空,则x的左子树中最右的节点为其前驱
- 若x的左子树为空,且x有一个前驱y,则y是x的最低祖先节点,且y的右儿子也是x的祖先,针对的是中序遍历下的前驱
|
|
5. Successor(后继)
找到某个节点的后继节点,返回为后继或者null。存在两种情况:
找结点(x)的后继结点。即,查找”二叉树中数据值大于该结点”的”最小结点”。
- 若节点x的右子树非空,则x的右子树中最左的节点为其后继
- 若x的右子树为空,且x有一个后继y,则y是x的最低祖先节点,且y的左儿子也是x的祖先,针对的是中序遍历下的后继
|
|
二叉查找树删除
二叉查找树的删除分为三种情况:
- 若被删除节点为叶子节点,则直接删除,不会影响二叉查找树的特性;
- 若节点node只有左子树或者右子树,则让node的子树成为node父节点的子树,代替node的位置;
- 若节点既有左子树又有右子树,则用node的后继(Successor)的值代替node的值,然后从二叉树中删除这个后继,这样就转换成第一或第二种情况。
|
|
|
|
二叉查找树销毁
二叉查找树销毁原理也很简单,使用递归,遍历每一个节点,将其销毁便可。
|
|
二叉查找树求深度
1. 递归求法
递归求二叉树深度比较简单,直接上代码:
|
|
2. 非递归求法
经典的非递归遍历,利用队列(std::queue),先将头节点入队列,若队列不为空,记出队列的节点为cur_node,若cur_node的左节点不为空,则入队列,若cur_node右节点不为空也入队列,如此循环。
此方法也可同时求树的最大宽度,以及访问某一层某一列的节点。
|
|