好。我有一个二叉树,这就是我想用它做的事情:
对于原始树中的每个节点: 如果它不是叶子,请用叶子节点替换它。 使用已删除的分支更新原始树上的计算。 将节点恢复为原样(现在树与开头的树相同)。
问题是:我正在使用堆栈遍历树。如果我将stack.pop()节点更改为叶子,则不会删除原始树中的任何分支。这就是为什么你可以这样做的原因:
int x=1
int y=x
y++
x仍然等于1.这是一个技术术语,但我忘了它。
那么如何编辑原始树中的节点并仍然遍历它呢?
这基本上就是我现在要遍历树的方式:
public void iterativePreorder(Node root) {
Stack nodes = new Stack();
nodes.push(root);
Node currentNode;
while (!nodes.isEmpty()) {
currentNode = nodes.pop();
Node right = currentNode.right();
if (right != null) {
nodes.push(right);
}
Node left = currentNode.left();
if (left != null) {
nodes.push(left);
}
//This is where you do operations on the currentNode
}
}
答案 0 :(得分:0)
从我的问题可以看出,对于每个Node
,你想要计算一些关于树的东西,好像那个节点是叶子一样。
要做到这一点,没有理由让该节点成为叶子,然后重新附加它。相反,您的逻辑可以简单地记住将哪个节点视为每个计算的叶子。
遍历树,对于每个Node
,我们称之为outerCurrentNode
,再次遍历树进行计算 - 但现在对于每个Node
,我们称之为{{1} },测试看看innerCurrentNode
。如果测试返回outerCurrentNode == innerCurrentNode
,请将true
视为叶子,忽略其子项。
编辑:以下是我建议(未经测试)的模拟:
innerCurrentNode
我正在使用递归而不是//entry point - called from directing code
public void iterativePreorder(Node root) {
iterativePreorderKernel(root, root);
}
//recursive method - keeps track of root in addition to current Node
private void iterativePreorderKernel(Node root, Node current) {
if (current.left() != null) {
iterativePreorderKernel(root, current.left());
}
if (current.right() != null) {
iterativePreorderKernel(root, current.right());
}
//for each Node in the tree, do calculations on the entire tree, pretending
//the current Node is a leaf
doCalculation(root, current);
}
//calculation method (also recursive) - takes a current Node, plus
//the Node to treat as a leaf
public void doCalculation(Node innerCurrent, Node pretendLeaf) {
//do calculation with inner current node
if (innerCurrent != pretendLeaf) {
if (innerCurrent.left() != null) {
doCalculation(innerCurrent.left(), pretendLeaf);
}
if (innerCurrent.right() != null) {
doCalculation(innerCurrent.right(), pretendLeaf);
}
}
}
,但两者都可以。 Stack
执行遍历,为每个iterativePreorder()
调用doCalculation()
,将其与根一起传递(以跟踪整个树)。然后该方法进行自己的遍历,进行计算,但在到达特别标记的Node
时停止。