[英]Iterative postorder traversal breaks at root node of tree
我实现了一种算法,用于迭代地打印二叉树的后序遍历。 整个算法都起作用,除了当它到达树的根部时会进入无限循环。
有人可以指出我正确的方向吗? 我已经在这个问题上停留了2天了。
void postorder_nonrec_2(treenode *root)
{
stack_t *s;
stack_init(&s, 100);
treenode *temp = root;
while(1)
{
while(root)
{
push(s, root);
root = root -> left;
}
if(stack_isEmpty(s))
break;
if(!top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
if(root == top(s) -> left)
{
root = top(s) -> right;
}
else if(root == top(s) -> right)
{
printf("%d ", pop(s) -> data);
root = NULL;
}
}
else
{
root = top(s) -> right;
}
}
}
也许在您使用的测试用例中,仅在根部存在一个无限循环,但是我认为该无限循环也可能发生在树的其他位置,具体取决于特定的树。
我认为问题是,当右侧有子级时,您不会正确继续弹出堆栈。
考虑一个简单的示例,其中我们的根节点1的左子节点为0,右子节点为2,并假设2的右节点为3。
在第一个循环中,我们将1和0压入堆栈。 然后0没有左子节点,因此root变为null。 堆栈不为空,因此我们继续。 0在堆栈的顶部,并且没有合适的子级,因此我们输入if语句的第一个分支。 然后我们打印出0,因为0是1的左孩子-1现在是堆栈的顶部-根变成2。
至此,我们回到顶部。 2是根,并被压入堆栈。 2没有左子节点,因此根变为空。 堆栈不为空。 2在堆栈的顶部。 它有一个正确的孩子,因此我们进入if语句的第二个分支。 这使3成为根。
我们回到外循环的顶部。 3是根,并被压入堆栈。 3没有左子节点,因此根变为空。 堆栈不为空。 3没有合适的孩子,因此我们进入if语句的第一个分支。 我们打印出3。然后因为3是2的正确子级-2现在位于堆栈的顶部-我们将2弹出堆栈,打印出2,并且根变为空。
我们回到循环的顶部。 根已经为空,因此没有任何内容被压入堆栈。 堆栈不为空。 1在堆栈的顶部。 此时,正确的做法是从堆栈中弹出1,因为我们已经处理了它的正确子级; 但是,1在堆栈的顶部,并且确实有一个正确的子代,因此我们进入if语句的第二个分支,而2成为根。 这种情况与前两段中的情况完全相同,其中1是堆栈上的唯一元素,而2是根,因此我们回到了无限循环。
如果我们更改示例,使3也有一个名为4的正确子元素,那么,如果我没看错,我们将永远不会打印出2并循环打印出4和3。
要解决此问题,只要要处理的元素是堆栈顶部的右子元素,就应该继续弹出堆栈。 我尚未对此进行编译或测试,但是我认为编写类似
if (!top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
while (!stack_isEmpty(s) && root == top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
}
if (!stack_isEmpty(s) && root == top(s) -> left)
{
// checking root == top(s) -> left is probably redundant,
// since the code is structured so that root is either
// a child of top(s) or null if the stack is not empty
root = top(s) -> right;
}
else
{
root = NULL;
// could actually break out of outer loop here, but
// to be more consistent with code in the question
}
}
发布此答案以提供@Evan VanderZee建议的解决方案的完整代码
void postorder_nonrec_2(treenode *root)
{
stack_t *s;
stack_init(&s, 100);
while(1)
{
while(root)
{
push(s, root);
root = root -> left;
}
if(stack_isEmpty(s))
break;
if (!top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
while (!stack_isEmpty(s) && root == top(s) -> right)
{
root = pop(s);
printf("%d ", root -> data);
}
root = NULL;
}
else
{
root = top(s) -> right;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.