所以,事实上,您可以总是将函数重构为尾递归......大多数使用其他语言编程的人将使用延续来有效地对其进行编码。但是,我们在这里更具体地研究 C/C++ 语言,所以我假设仅通过对函数本身进行编码来摆脱这种情况(我的意思是不向语言添加通用延续框架)。
假设您有一个迭代版本的函数,应该如下所示:
void iterative() {
while (cond)
dosomething()
}
那么,把它变成一个尾递归函数就简单了:
void tailrecursive() {
if (!cond)
return;
dosomething();
tailrecursive();
}
大多数时候,您需要将“状态”传递给递归调用,这会添加一些以前没有用的额外参数。在您的特定情况下,您有一个前序树遍历:
void recursive_preorder(node n) {
if (n == visited)
return;
dosomething(n);
foreach child_node in n.getChildren() {
recursive_preorder(child_node);
}
}
迭代等效需要引入一个堆栈来记住资源管理器节点(因此,我们添加了推送/弹出操作):
void iterative_preorder(node n) {
if (n == visited)
return;
stack worklist = stack().push(n);
while (!worklist.isEmpty()) {
node n = worklist.pop()
dosomething (n);
foreach child_node in n.getChildren() {
worklist.push(child_node);
}
}
}
现在,采用这个迭代版本的前序树遍历并将其转换为尾递归函数应该给出:
void tail_recursive_preorder_rec(stack worklist) {
if (!worklist.isEmpty()) {
node n = worklist.pop()
dosomething (n);
foreach child_node in n.getChildren() {
worklist.push(child_node);
}
}
tail_recursive_preorder_rec(worklist)
}
void tail_recursive_preorder (node n) {
stack worklist = stack().push(n);
tail_recursive_preorder_rec(worklist);
}
而且,它为您提供了一个尾递归函数,该函数将被编译器很好地优化。尽情享受吧!