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
相关产品推荐
相关产品推荐

