Algorithm 无堆栈帧代码重复的递归变换

Algorithm 无堆栈帧代码重复的递归变换,algorithm,recursion,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:

我有以下伪代码:

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;
}
函数X(数据、限制、级别=0) { 结果=[]; foreach(Y(数据,级别)作为实体){ if(液位<限值){ 结果=结果+X(实体、限制、级别+1); }否则{ //普通递归情况: 结果=结果+Z(实体); } } 返回结果; } 我需要将其转换为普通(例如,没有递归调用)。到目前为止,关于如何优雅地做到这一点,我没有任何想法。在回答之后,我看到我必须构建整个堆栈框架,这些框架基本上是代码重复(即,我将用不同的返回地址一次又一次地放置相同的代码)

或者我尝试了一些类似的东西,比如-哪里有短语

  • 查找不是尾部调用的递归调用
  • 确定该调用与其返回语句之间正在进行的工作
  • 但我不明白,当“功”发生在内部循环中时,如何才能识别它

    因此,我的问题是,上面的所有示例都提供了“工作很容易识别”的情况,因为功能中没有控制指令。我理解编译级递归背后的概念,但我要避免的是代码重复。所以


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

    它看起来像是一种算法,将嵌套数据结构(列表列表)降级并将其展平为单个列表。如果在问题中有这样一个简单的描述就好了

    要做到这一点,您需要跟踪多个索引/迭代器/游标,每一级都有一个。递归实现通过使用调用堆栈来实现这一点。一个非递归的实现需要一个可以推/弹出的工具

    由于您不必在调用堆栈上保存上下文(寄存器)和返回地址,只需保存实际的迭代器(例如数组索引),因此这可以大大节省空间


    当您在Y的结果上循环并且需要调用X或Z时,将当前状态推送到堆栈上。分支回到
    foreach
    的开头,并在新实体上调用Y。当你到达一个循环的末尾时,如果有一个旧状态,弹出这个循环,在这个循环的中间拾取。

    你能用伪代码来详细说明一下吗?关于X、Y和Z呼叫?而且,这不是列表的列表迭代,它实际上是树遍历到某个级别并将其展平(但我同意这是类似的)@AlmaDo:我扩展了一些。我添加的链接(谷歌首次点击“堆栈数据结构”)有一个递归和手动堆栈函数的例子,用于解决河内塔问题。看看该函数如何使用堆栈。如果你仍然没有得到它,那么当你试图弄明白这一点时,请详细说明你被卡在了什么地方。这是保存
    foreach
    循环状态的方式吗?我也不知道,因为您刚刚用一些虚构的语言发布了伪代码,可以返回列表。推整个列表将是愚蠢的。“手动实现的堆栈”,等等-抱歉,但我知道这件事。问题是如何做到这一点。我对清晰的执行有问题。我现在所做的只是复制堆栈帧(因此,每个帧包含相同的代码,并且必须重复我们定义的级别的次数)。如何将其转化为一个清晰的堆栈实现,我现在还不能掌握。注意,这个问题源于这样一个事实:在一个局部空间中,实际上不是一个而是多个递归调用(数量等于
    Y()
    )返回的元素计数)@AlmaDo:我在上次编辑中添加的不仅仅是该链接。最后两段正是你要问的问题。检查差异。谢谢你,我投你一票——虽然我已经解决了这个问题,但阅读一般见解仍然很有用