莫里斯inorder遍历

时间:2016-04-27 20:04:59

标签: algorithm tree binary-tree graph-traversal

从这里学习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;
            }   

        } 

    } 

1 个答案:

答案 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持有Bpre将设置为A',与A相同。 pre.right == A'.right == A.right == current。因为这意味着已经访问了A'节点,它会打破循环并重新构建它,这将导致您的下一个问题。

<强> Q2

同样,这种情况在树的重建之前永远不会发生,但在重建之后,这就是&#34;做什么&#34;当您到达已经访问过的节点时这又引出了你的下一个问题。

<强> Q3

pre.right设置为null,因为它意味着在重建之前,pre.right原来是空的。查看重建后的案例,节点Bpre设置为A,这是一个叶节点,并且没有正确的子节点。因此将其修复:

  B
 / \
A   C
     \
      D
     / \
    B'  F
       / \
      E   G

正如您所看到的,A'只变成了A,因为它的正确孩子不再是B而是null

基本上,为了帮助您更好地理解它:

  • Morris遍历重建树以使其具有根,因为它是最左边的节点(还要注意它现在有循环路径)
  • 一旦重建,它将会访问,然后将重建修复为原始形式。