没有堆栈帧的递归转换代码重复

时间:2015-10-28 17:04:01

标签: algorithm recursion

我有以下伪代码:

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这样的东西 - 那里有一个短语

  
      
  1. 找一个不是尾调用的递归调用。
  2.   
  3. 确定该呼叫与其返回声明之间正在进行的工作。
  4.   

但我不明白&#34;如何工作&#34;在内部循环内发生的情况下进行识别。

所以,我的问题是,上面的所有例子都提供了可以轻松识别&#34;工作的情况&#34;因为函数内没有控制指令。我理解在编译级别上递归的概念,但我想避免的是代码重复。所以,

我的问题:如何处理上面的伪代码转换并不意味着代码重复模拟堆栈帧?

1 个答案:

答案 0 :(得分:1)

它看起来像一个算法来下降嵌套数据结构(列表列表)并将其展平为单个列表。在问题中有一个简单的描述会很好。

要做到这一点,你需要跟踪多个索引/迭代器/游标,每个级别一个,你已经通过。递归实现通过使用调用堆栈来实现。非递归实现需要manually-implemented stack data structure,您可以在其中推送/弹出内容。

由于您不必在调用堆栈上保存上下文(寄存器)和返回地址,只需要实际的迭代器(例如数组索引),这可以提高空间效率。

当您循环Y的结果并需要调用X或Z时,将当前状态推送到堆栈。转回foreach的开头,并在新实体上调用Y.当你到达循环结束时,如果有循环,则弹出旧状态,并在该循环的中间拾取。