C 将递归二叉树遍历转换为迭代二叉树遍历
我被要求编写迭代版本,但我编写了递归版本,即C 将递归二叉树遍历转换为迭代二叉树遍历,c,recursion,iteration,binary-tree,imperative-programming,C,Recursion,Iteration,Binary Tree,Imperative Programming,我被要求编写迭代版本,但我编写了递归版本,即 void inorderTraverse(BinaryTree root) { if(root==NULL) printf("%d",root->id); else { inorderTraverse(root->left); printf("%d",root->id); inorderTraverse(root->right);
void inorderTraverse(BinaryTree root)
{
if(root==NULL)
printf("%d",root->id);
else
{
inorderTraverse(root->left);
printf("%d",root->id);
inorderTraverse(root->right);
}
}
我不是在寻找代码,我想了解如何做到这一点。如果这只是最后一个递归调用,我就会这样做
void inorderTraverse(BinaryTree root)
{
while(root!=NULL)
{
printf("%d",root->id);
root=root->right;
}
}
但是当有两个递归调用时,如何转换为迭代程序?
以下是类型定义
struct element{
struct element* parent;
int id;
char* name;
struct element* left;
struct element* right;
};
typedef element* BinaryTree;
这就是我的想法,我走对了吗
temp=root;
while(1)
{
while(temp!=NULL)
{
push(s,temp);
temp=temp->left;
continue;
}
temp=pop(s);
if(temp==NULL)
return;
printf("%d\t",temp->data);
temp=temp->right;
}
您看到的问题是,您需要“记住”上次迭代的位置。
在执行递归时,程序内部使用“堆栈”来记住返回的位置。
但当进行迭代时,它不会 虽然。。。这给了你一个想法吗?我想不出一个真正优雅的方法来立即迭代完成这项工作 一种可能是使用一种“标记算法”,从所有节点“未标记”开始,并在处理节点时“标记”节点。标记可以添加到对象模型中,也可以保存在单独的实体中 伪代码:
for (BinaryTree currentNode = leftmostNode(root); currentNode != null; currentNode = nextNode(currentNode)):
print currentNode;
currentNode.seen = true;
sub nextNode(BinaryTree node):
if (!node.left.seen):
return leftmostNode(node.left)
else if (!node.seen)
return node
else if (!node.right.seen)
return leftmostNode(node.right)
else
return nextUnseenParent(node)
sub leftmostNode(BinaryTree node):
while (node.left != null)
node = node.left
return node;
sub nextUnseenParent(BinaryTree node):
while (node.parent.seen)
node = node.parent
return node.parent
我想当然地认为,从父节点到左节点的迭代不是问题。问题是要知道从一个节点上升到父节点时要做什么:是应该选择正确的子节点,还是应该再上升一个父节点 以下技巧将帮助您: 在向上移动之前,请记住当前节点。然后往上走。现在您可以比较:您是否在左侧节点:然后选择右侧节点。否则,再上一个父节点
为此,您只需要一个引用/指针。有一种将递归遍历转换为迭代器的通用方法,它使用一个连接多个迭代器提供者(返回迭代器的lambda表达式)的惰性迭代器。查看我的。能否显示
BinaryTree
界面?有可能得到一个树节点的父节点吗?可能的重复,我知道这与在堆栈上推东西然后弹出它们有关,但我真的不知道该推什么,何时弹出,以及如何。好的,我可以从推所有节点开始,直到我到达最左边的叶子,然后我开始弹出,现在在弹出第一个后,我把右边的子对象推到stach上,一直推到这个子树最左边的叶子,现在我走到右边的树上,到达这个子树最右边的叶子,但是现在我怎么知道我需要做多少POP才能到达原始树最左边叶子的父级呢?如果可以的话,请帮我多做一些堆叠的事情。@Karan:我不确定我是否完全遵循了你提到的,但你想做的是这样做:(1)按当前节点并尽可能多次地按其左子节点(即,直到没有左节点为止),(2)弹出最后一个节点(这有返回值),(3)对弹出的最后一个节点的右子节点(如果有)重复步骤1。@Karan:我不确定为什么有if(temp==NULL)
在您的代码中--您从不推送NULL
,那么为什么要弹出NULL
?或者这是一种空虚状态的信号?但除此之外,它似乎很好。。。你试过了吗?我也只是想要这样的东西,但这算是一个迭代版本,对吧?而且,我不认为这是一个无序的遍历,事实上,你是从根开始打印的。“迭代步骤”比通常要复杂一些,但它只包含for
循环,while
循环,没有递归调用,所以我认为它应该是迭代的。