我被要求编写迭代版本,但我编写了递归版本,即
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;
}
答案 0 :(得分:3)
您遇到的问题是您需要“记住”您正在迭代的最后一个地方。
在进行递归时,程序在内部使用“堆栈”来记住返回的位置
但是在进行迭代时,却没有。
虽然......这会给你一个想法吗?
答案 1 :(得分:0)
我无法想到一个真正优雅的方式来迭代地执行此操作。
一种可能性可能是使用“标记算法”,您可以在处理完所有节点的“未标记”和“标记”节点时开始使用。标记可以添加到对象模型中,也可以保存在单独的实体中。
伪代码:
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
答案 2 :(得分:0)
我认为理所当然,从父节点迭代到左边节点不是问题。问题是要知道当从一个节点上升到父节点时该怎么做:你应该选择正确的子节点还是再增加一个父节点?
以下技巧可以帮助您:
在向上之前记住当前节点。然后向上走。现在您可以比较:您是否在左侧节点中:然后选择正确的节点。否则再上一个父节点。
您只需要一个参考/指针。
答案 3 :(得分:0)
通过使用连接多个迭代器供应商的lazy迭代器(lambda表达式返回迭代器),有一种将递归遍历转换为迭代器的一般方法。查看我的Converting Recursive Traversal to Iterator。