C 是否可以将每个递归都更改为迭代?
每个递归函数都可以转换为迭代吗?递归函数应该具有什么特征才能使用迭代实现 我一直在尝试使用迭代定义下面的函数,但似乎没有成功!它应该探索迷宫中的所有路径(节点)。有人能用迭代重写这个吗?如果不可能,为什么不呢C 是否可以将每个递归都更改为迭代?,c,recursion,iteration,C,Recursion,Iteration,每个递归函数都可以转换为迭代吗?递归函数应该具有什么特征才能使用迭代实现 我一直在尝试使用迭代定义下面的函数,但似乎没有成功!它应该探索迷宫中的所有路径(节点)。有人能用迭代重写这个吗?如果不可能,为什么不呢 typedef int[0,99] id_t; bool visited[id_t]; int path[id_t]; int pathCounter = 0; struct { id_t id; bool free; int neighborNode[4];
typedef int[0,99] id_t;
bool visited[id_t];
int path[id_t];
int pathCounter = 0;
struct {
id_t id;
bool free;
int neighborNode[4];
} nodeMap[id_t];
void findPath(int current){
visited[current] = true;
for (i : int[0, 3]){
if(nodeMap[nodeMap[current].neighborNode[i]].free == true && visited[nodeMap[current].neighborNode[i]] == false && nodeMap[current].neighborNode[i] != -1){
path[pathCounter] = nodeMap[nodeMap[current].neighborNode[i]].id;
pathCounter++;
findPath(nodeMap[current].neighborNode[i]);
path[pathCounter] = nodeMap[current].id;
pathCounter++;
}
}
path[0] = current;
}
扩展:是否可以在不实现自己的堆栈的情况下将所提到的递归函数转换为迭代?其中一个答案是,每个尾部递归函数都可以转换为迭代,而无需使用堆栈结构……如果是这样,那么每个递归函数都可以转换为尾部递归吗?如何转换?根据所有递归定义的函数都可以转换为迭代函数。是的,每个递归函数都可以通过一个相当机械的过程转换为迭代函数
回想一下,编译器使用堆栈实现递归,堆栈通常在CPU硬件中实现。您可以构建自己的软件堆栈,使其适合保持函数的状态(即其局部变量),将初始状态推送到该堆栈上,并编写
while
循环,将新状态推送到堆栈上,而不是进行递归调用,弹出堆栈而不是返回,并在堆栈不为空时继续该过程。通常可以将任何递归算法转换为循环。方法很简单:我们可以模拟编译器如何为函数调用生成代码:输入函数,从函数返回,然后继续执行
要将递归函数转换为迭代循环,可以:
- 定义一个记录,该记录存储函数的参数和局部变量。这相当于堆栈帧
- 定义一个堆栈,其中记录一个已推送到的文件。这类似于程序堆栈
- 调用函数时,创建参数和局部变量当前值的记录,并推送到堆栈
- 从函数返回时,从堆栈中弹出并用记录中的值覆盖当前值
上面的整个过程是在while循环中完成的,当堆栈为空时将退出,与前面提到的其他答案一样,通过模拟堆栈在技术上是可行的。但我猜你不想这么做。您可能需要一个不使用堆栈的迭代解决方案。如果是这种情况,您需要一个尾部递归函数。那是唯一可能的办法。您可以将每个尾部递归函数重写为命令式函数,而无需模拟堆栈。如果您有一个简单的“尾部”递归,则可以使用循环(例如阶乘函数)。在更复杂的函数中,必须使用
堆栈
结构和while(!stack.empty())
循环。但是,如果您有非常复杂的递归,例如河内塔楼
,合并排序
,以及打印真值表
,则必须使用堆栈
,与前面一样,使用while
循环,但使用开关
语句来确定调用的当前状态
递归:
void mergeSort(int start, int end)
{
if (start < end)
{
mergeSort(start, (start + end) / 2);
mergeSort((start + end) / 2 + 1, end);
Merge(start, end);
}
}
void mergeSort()
{
stack<int> st;
st.push(1);
int status;
while (!st.empty())
{
status = st.pop();
switch (status)
{
case 1:
....
break;
case 2:
break;
}
}
}
void合并排序(int开始,int结束)
{
如果(开始<结束)
{
合并排序(开始,(开始+结束)/2);
合并排序((开始+结束)/2+1,结束);
合并(开始、结束);
}
}
迭代:
void mergeSort(int start, int end)
{
if (start < end)
{
mergeSort(start, (start + end) / 2);
mergeSort((start + end) / 2 + 1, end);
Merge(start, end);
}
}
void mergeSort()
{
stack<int> st;
st.push(1);
int status;
while (!st.empty())
{
status = st.pop();
switch (status)
{
case 1:
....
break;
case 2:
break;
}
}
}
void mergeSort()
{
斯塔克街;
圣普什(1);
智力状态;
而(!st.empty())
{
状态=圣普();
开关(状态)
{
案例1:
....
打破
案例2:
打破
}
}
}
我强烈建议您详细解释这个过程。这有点太短,不能作为答案。也许如果你用更多的评论来扩展它。没错!您能告诉我更多关于如何将我的函数转换为尾部递归,以便以后我可以使用迭代重写它吗?可以将任何递归转换为尾部递归吗?不能将每个递归函数都转换为尾部递归函数。也许你的功能有可能,我还不确定;)这个函数是树递归的,所以我想这就排除了在不使用辅助数据结构的情况下将其转换为尾部递归的可能性。这个函数怎么样?这是一个尾部递归的例子吗?如果不是,它是否可以转换为尾部递归?怎么做?@SabaAhang它也不是很复杂。它可以使用堆栈实现。我提供的
pdf
非常好。您可以从中学习如何使用stackI实现它我有点不喜欢实现我自己的堆栈,是否仍然可以将我的函数转换为迭代?@SabaAhang如果是尾部调用,则可以在没有堆栈的情况下重写递归(现代编译器将此作为优化)。对于您的特定问题,堆栈只是一个由int
s和代表“堆栈指针”的标量int
组成的数组,因此实现堆栈非常简单。实际上需要存储两个数字:current和i。另请参阅上的Wikipedia。可能的