问询BST节点前驱查找代码中循环段的功能与执行逻辑
解析BST前驱节点查找中的循环逻辑
嘿,我来给你拆解这段循环的逻辑,其实它就是BST里当节点没有左子树时,找前驱的核心步骤~
先把这段循环代码单独拎出来看:
TreeNode y = parent; TreeNode x = node; while (y != null && x == y.getLeft()) { x = y; y = y.getParent(); } return y;
核心功能
这段循环的作用是:当目标节点没有左子树时,向上回溯查找它的前驱节点——也就是BST中比该节点小的最大节点。如果节点是整棵树里最小的那个,循环最终会返回null,表示没有前驱。
为什么需要这段循环?
在BST里,节点的前驱分两种情况:
- 如果节点有左子树,前驱就是左子树里的最大节点(这就是代码开头
findMaximum(node.getLeft())的逻辑); - 如果节点没有左子树,前驱就得往上找——找第一个把当前节点所在分支当作右子树的祖先。因为BST的规则是:左子树节点都比父节点小,右子树节点都比父节点大。如果当前节点是某个祖先的右孩子,那这个祖先一定比当前节点小,而且是最近的那个比它小的节点,也就是我们要找的前驱。
循环的具体执行过程
我用一个实际的BST例子来一步步拆解,假设我们有这样的树:
10 / \ 5 15 / \ / 3 7 12
例子1:查找节点7的前驱
节点7没有左子树,进入这段循环:
- 初始化:
y = 5(7的父节点),x = 7 - 检查循环条件:
y != null(成立),但x == y.getLeft()?7是5的右孩子,这个条件不成立,循环直接终止 - 返回
y = 5——这正是7的前驱,完全正确。
例子2:查找节点3的前驱
节点3没有左子树,进入循环:
- 初始化:
y = 5(3的父节点),x = 3 - 检查条件:
y != null(成立),且x == y.getLeft()(3是5的左孩子,条件成立),进入循环体:x更新为y(也就是5),y更新为y.getParent()(也就是10)
- 再次检查条件:
y != null(成立),且x == y.getLeft()(5是10的左孩子,条件成立),再次进入循环体:x更新为10,y更新为y.getParent()(也就是null)
- 现在
y == null,循环终止,返回null——因为3是树中最小的节点,确实没有前驱。
例子3:查找节点12的前驱
节点12没有左子树,进入循环:
- 初始化:
y = 15(12的父节点),x = 12 - 检查条件:
y != null(成立),且x == y.getLeft()(12是15的左孩子,条件成立),进入循环体:x更新为15,y更新为10(15的父节点)
- 再次检查条件:
y != null(成立),但x == y.getLeft()?15是10的右孩子,条件不成立,循环终止 - 返回
y = 10——这就是12的前驱,因为10是最近的比12小的祖先,符合BST的规则。
总结执行逻辑
- 初始化:用
y跟踪当前节点的父节点,x跟踪当前节点(后续会逐步向上回溯) - 循环判断:只要还没回溯到树外(
y != null),且当前节点(x)是父节点(y)的左孩子,就继续往上走——因为这时候父节点比x大,不可能是前驱 - 终止返回:当循环停下时,要么
y是null(当前节点是树中最小节点),要么x是y的右孩子——这时候y就是我们要找的前驱节点。
内容的提问来源于stack exchange,提问作者anon anon
相关产品推荐
相关产品推荐

