从这里学习morris inorder遍历:http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/和Explain Morris inorder tree traversal without using stacks or recursion
我很困惑。评论中有3个问题。欢迎提供帮助。感谢
while (current != null) {
if (current.left == null) {
visit(current);
current = current.right;
} else {
pre = current.left;
while (pre.right != null && pre.right != current) {
pre = pre.right;
} // Q1: why "pre.right != current"?
// pre is initialized as current.left and will go right until null,
// why compare pre.right with current?
if (pre.right == null) {
pre.right = current;
current = current.left;
} else { // Q2: In which case, pre.right is not null and program gets here?
pre.right = null;// Q3: why set pre.right to null?
visit(current);
current = current.right;
}
}
}
答案 0 :(得分:1)
好吧,如果我理解正确,这次遍历实质上是重构树,以便最左边的节点位于树的根部。所以就像这样开始:
D
/ \
B F
/ \ / \
A C E G
看起来像这样:
A
\
B
/ \
A' C
\
D
/ \
B' F
/ \
E G
其中A'
是A
及其所有子树。
访问后,它将重建树。
回答你的问题:
<强> Q1 强>
在重建之前,pre.right != current
将永远不会成为循环结束条件,即它永远不会成立。但是,在重建之后,假设current
持有B
。 pre
将设置为A'
,与A
相同。 pre.right == A'.right == A.right == current
。因为这意味着已经访问了A'
节点,它会打破循环并重新构建它,这将导致您的下一个问题。
<强> Q2 强>
同样,这种情况在树的重建之前永远不会发生,但在重建之后,这就是&#34;做什么&#34;当您到达已经访问过的节点时这又引出了你的下一个问题。
<强> Q3 强>
pre.right
设置为null
,因为它意味着在重建之前,pre.right
原来是空的。查看重建后的案例,节点B
,pre
设置为A
,这是一个叶节点,并且没有正确的子节点。因此将其修复:
B
/ \
A C
\
D
/ \
B' F
/ \
E G
正如您所看到的,A'
只变成了A
,因为它的正确孩子不再是B
而是null
。
基本上,为了帮助您更好地理解它: