【发布时间】:2011-03-31 16:11:16
【问题描述】:
有人可以帮我理解以下不使用堆栈或递归的莫里斯中序树遍历算法吗?我试图了解它是如何工作的,但它只是逃避了我。
1. Initialize current as root
2. While current is not NULL
If current does not have left child
a. Print current’s data
b. Go to the right, i.e., current = current->right
Else
a. In current's left subtree, make current the right child of the rightmost node
b. Go to this left child, i.e., current = current->left
我了解树的修改方式为将current node 设为max node 中的right child 在right subtree 中,并使用此属性进行中序遍历。但除此之外,我迷路了。
编辑:
找到了这个随附的 c++ 代码。我很难理解树在修改后是如何恢复的。神奇之处在于else 子句,一旦修改了右叶就会被命中。详情见代码:
/* Function to traverse binary tree without recursion and
without stack */
void MorrisTraversal(struct tNode *root)
{
struct tNode *current,*pre;
if(root == NULL)
return;
current = root;
while(current != NULL)
{
if(current->left == NULL)
{
printf(" %d ", current->data);
current = current->right;
}
else
{
/* Find the inorder predecessor of current */
pre = current->left;
while(pre->right != NULL && pre->right != current)
pre = pre->right;
/* Make current as right child of its inorder predecessor */
if(pre->right == NULL)
{
pre->right = current;
current = current->left;
}
// MAGIC OF RESTORING the Tree happens here:
/* Revert the changes made in if part to restore the original
tree i.e., fix the right child of predecssor */
else
{
pre->right = NULL;
printf(" %d ",current->data);
current = current->right;
} /* End of if condition pre->right == NULL */
} /* End of if condition current->left == NULL*/
} /* End of while */
}
【问题讨论】:
-
我以前从未听说过这种算法。相当优雅!
-
我认为指出the source of the pseudo-code + code 可能有用(大概)。
-
在上面的代码中,下面这行不是必须的:
pre->right = NULL; -
我认为伪代码有一个重要的遗漏错误。在“Else”的步骤“a”中,它表示标记
current的前任并向左移动。这应该说类似“如果我们在找到它自己的前任时遇到current,则取消线程(可选,如果您不想让树保持线程)并向右移动”。我认为这就是@Talonj 在他们出色的答案中所说的“循环的双重条件”的意思。这里的教训是代码比描述更重要。
标签: c++ binary-tree tree-traversal