You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java迭代实现二叉树反转失效的引用问题排查与修复

问题根因

你的判断方向基本正确,但对Java引用机制的表述有偏差:

  • Java中TreeNode是引用类型,栈里存储的是对象引用的 值拷贝,不是节点对象本身的副本,堆里的节点对象是全局唯一的,你拿到引用后可以直接修改对象内部的字段。
  • 你代码里的交换逻辑完全没有修改原树结构:
    TreeNode nd1 = s.pop();
    TreeNode nd2 = s.pop();
    TreeNode temp = nd1;
    nd1 = nd2;
    nd2 = temp;
    
    这段代码仅仅交换了nd1、nd2两个局部变量自身存储的引用地址,根本没有修改任何节点的left/right字段——就像你交换了两个写着门牌号的纸条,根本没动房子里的任何东西,原树自然不会有任何变化。
  • 你原有逻辑还有一个隐藏缺陷:你只在nd1/nd2非空时把它们的子节点压栈,但根本没有把空节点正确挂载到树的对应位置,就算修复了交换逻辑,单边子节点为空的场景也会出问题。
修复方案

你原本“用栈迭代处理节点”的思路完全可行,只是不需要强行一次弹出两个兄弟节点处理——更简单的逻辑是每次只压单个节点入栈,弹出节点后 直接修改该节点自身的left、right字段,交换它的两个子节点,再把非空子节点压栈处理即可,这种写法不需要记录父节点,逻辑更简洁也不容易出错:

public TreeNode invertTree(TreeNode root) {
    if (root == null) return root;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);
    
    while (!stack.isEmpty()) {
        TreeNode curr = stack.pop();
        // 直接修改当前节点的左右孩子字段,修改会直接作用在原树的节点对象上
        TreeNode temp = curr.left;
        curr.left = curr.right;
        curr.right = temp;
        
        // 非空子节点入栈,等待后续反转
        if (curr.left != null) stack.push(curr.left);
        if (curr.right != null) stack.push(curr.right);
    }
    return root;
}

如果你想坚持最初“每次处理一对兄弟节点”的思路,本质上和上面的逻辑是一致的,只需要把栈中存储的内容从子节点改成父节点即可,每次弹出父节点后交换它的两个子节点,再把子节点压栈,效果完全相同。

注:这个问题和C中“只交换局部指针变量、没修改指针指向的内容”本质是同一个问题,C中需要传二级指针或者指针引用才能修改外层指针的值,对应到Java就是必须直接修改对象内部的字段,而不是交换局部变量的引用指向。

内容的提问来源于stack exchange,提问作者Allan T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:48:15