有人可以在不使用堆栈或递归的情况下帮助我了解以下Morris有序树遍历算法吗?我试图理解它是如何工作的,但是它只是在逃避我。
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
是right child
,将max node
in做成in,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 */
}
如果我没看错算法,这应该是其工作方式的一个示例:
X
/ \
Y Z
/ \ / \
A B C D
首先,X
是根,因此将其初始化为current
。X
有一个左孩子,所以X
它成为X
左子树的最右孩子-X
有序遍历的直接前任。这样X
就做成了正确的孩子B
,然后current
设置为Y
。树现在看起来像这样:
Y
/ \
A B
\
X
/ \
(Y) Z
/ \
C D
(Y)
上面提到了Y
及其所有子项,由于递归问题而将其省略。无论如何,重要的部分都会列出。现在树已链接回X,遍历继续...
A
\
Y
/ \
(A) B
\
X
/ \
(Y) Z
/ \
C D
然后A
输出,因为它没有左子,然后current
返回Y
,A
在上一次迭代中将其作为右子。在下一次迭代中,Y有两个孩子。但是,循环的双重条件使其在到达自身时停止,这表明它的左子树已被遍历。因此,它会自行打印,并继续其右侧的子树B
。
B
进行打印,然后current
变为X
,它经过与检查相同的检查过程Y
,还意识到它的左子树已被遍历,并继续Z
。树的其余部分遵循相同的模式。
不需要递归,因为返回到(sub)tree根的链接不再依赖于通过堆栈的回溯,而是移动到了在递归有序树遍历算法中无论如何都将被访问的点-左子树已完成。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句