#BW222. 二叉搜索树
二叉搜索树
题目描述
小蓝是一个热爱编程的图书管理员。他管理的图书馆里有一批书籍,每本书都有一个唯一的编号(正整数)。为了方便查找和整理,小蓝决定用二叉搜索树(Binary Search Tree, BST) 来维护这些编号。BST 满足:对于任意一个节点,其左子树中所有节点的编号都小于该节点,右子树中所有节点的编号都大于该节点。
初始时,树为空。小蓝需要执行一系列操作来管理书籍:
- 插入(
I x):将编号为 的书加入树中。如果 已存在,则忽略(不重复插入)。 - 删除(
D x):将编号为 的书从树中移除。删除时,如果该节点有两个孩子,则用其中序前驱(即左子树中的最大值)来替代它,然后删除前驱节点;如果只有一个孩子或没有孩子,则直接删除。 - 修改(
M x y):将编号 的书籍改为编号 。操作规则:只有当 存在且 不存在时,才先删除 ,再插入 ;否则忽略该操作。 - 查询(
Q):小蓝需要知道当前所有书籍编号的升序排列(即中序遍历结果),以及这棵树的高度(根节点高度为 ,空树高度为 )。
现在,给你一系列操作,请你在每次查询时输出所需信息,并在所有操作结束后(实际上查询后程序输出)输出最终状态。
输入格式
第一行包含一个正整数 (),表示操作总数。
接下来 行,每行一个操作,格式如下:
I x:插入整数 ()D x:删除整数 ()M x y:修改编号 为 ()Q:查询当前树的中序遍历序列及高度
输出格式
对于每个 Q 操作,输出两行:
- 第一行:当前树的中序遍历序列,整数之间用空格分隔。若树为空,则输出一个空行。
- 第二行:一个整数,表示树的高度(根节点高度为 )。
注意:题目不要求最后单独输出,所有 Q 操作的结果依次输出即可。
输入输出样例
9
I 5
I 3
I 8
I 2
I 4
D 3
M 8 6
I 7
Q
2 4 5 6 7
3
6
I 10
I 5
I 15
M 5 12
D 10
Q
12 15
2
说明/提示
操作详解
-
插入(I)
从根节点开始,若待插入值小于当前节点值,则向左走;若大于,则向右走。遇到空位置则插入新节点;若值已存在,则不做任何事。 -
删除(D)
找到待删节点del。- 若
del没有左孩子或没有右孩子(即至少一个孩子为空),则直接用其非空孩子(若存在)替代del的位置;若del是叶子,则直接移除。 - 若
del左右孩子均存在,则找到del左子树中的最大值节点(即中序前驱pred),将pred的值复制给del,然后删除pred(删除时pred必无右孩子,可能有左孩子,按上述规则删除即可)。
- 若
-
修改(M)
先检查 是否存在且 是否不存在。若满足,则执行D x再执行I y。否则忽略。注意,若 ,也视为忽略。 -
查询(Q)
- 中序遍历:递归地按“左-根-右”的顺序访问所有节点,结果即为编号的升序序列。
- 高度:根节点高度为 ,空树高度为 。树的高度等于从根到最远叶子节点经过的边数加一,也可以理解为最大层数。
样例 1 详解
我们一步一步构造:
I 5→ 树:5(根)I 3→5的左孩子为3I 8→5的右孩子为8I 2→3的左孩子为2I 4→3的右孩子为4此时树结构:5 / \ 3 8 / \ 2 4D 3:待删节点3有两个孩子(左2,右4)。找前驱:左子树最大值是2(2无右子)。将2的值复制到3的位置,然后删除原2。树变为:
(注意5 / \ 2 8 \ 43节点现在值为2,其左孩子为空,右孩子为4)M 8 6:检查8存在且6不存在 → 删除8,插入6。删除8时,8是叶子,直接移除;插入6时,由于6 > 5,应到右子树,此时右子树为空,所以6成为5的右孩子。树变为:5 / \ 2 6 \ 4I 7:插入7,从根5开始,向右到6,再向右,插入7作为6的右孩子。树:5 / \ 2 6 \ \ 4 7Q:中序遍历:先左子树2→ 访问2,然后右孩子4,再根5,然后右子树6,然后7→ 序列:2 4 5 6 7。高度:根5层 ,2和6层 ,4和7层 ,所以高度为 。
样例 2 详解
I 10→ 根10I 5→10左5I 15→10右15M 5 12:5存在,12不存在 → 删除5(叶子),插入12。插入12时,从根10出发,12 > 10向右到15,再向左(空)插入,所以12成为15的左孩子。树:10 \ 15 / 12D 10:删除根10,它只有右孩子15,直接用15替代根。树:15 / 12Q:中序为12 15,高度为 (根15层 ,12层 )。
数据范围与注意事项
- 对于 的数据:
