我有以下伪代码:
function X(data, limit, level = 0)
{
result = [];
foreach (Y(data, level) as entity) {
if (level < limit) {
result = result + X(entity, limit, level + 1);
} else {
//trivial recursion case:
result = result + Z(entity);
}
}
return result;
}
我需要变成普通的(例如没有递归调用)。到目前为止,我没有关于如何优雅地做到这一点的想法。在https://docs.docker.com/reference/commandline/commit/回答之后,我看到我必须构造整个堆栈帧,这些帧基本上是代码重复(即我会一次又一次地使用不同的返回地址放置相同的代码)。
或者我试过像this这样的东西 - 那里有一个短语
- 找一个不是尾调用的递归调用。
- 确定该呼叫与其返回声明之间正在进行的工作。
醇>
但我不明白&#34;如何工作&#34;在内部循环内发生的情况下进行识别。
所以,我的问题是,上面的所有例子都提供了可以轻松识别&#34;工作的情况&#34;因为函数内没有控制指令。我理解在编译级别上递归的概念,但我想避免的是代码重复。所以,
我的问题:如何处理上面的伪代码转换并不意味着代码重复模拟堆栈帧?
答案 0 :(得分:1)
它看起来像一个算法来下降嵌套数据结构(列表列表)并将其展平为单个列表。在问题中有一个简单的描述会很好。
要做到这一点,你需要跟踪多个索引/迭代器/游标,每个级别一个,你已经通过。递归实现通过使用调用堆栈来实现。非递归实现需要manually-implemented stack data structure,您可以在其中推送/弹出内容。
由于您不必在调用堆栈上保存上下文(寄存器)和返回地址,只需要实际的迭代器(例如数组索引),这可以提高空间效率。
当您循环Y的结果并需要调用X或Z时,将当前状态推送到堆栈。转回foreach
的开头,并在新实体上调用Y.当你到达循环结束时,如果有循环,则弹出旧状态,并在该循环的中间拾取。