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:我在上次编辑中添加的不仅仅是该链接。最后两段正是你要问的问题。检查差异。谢谢你,我投你一票——虽然我已经解决了这个问题,但阅读一般见解仍然很有用