从递归到迭代的方法

在多年的编程中,我已经使用了不少递归来解决简单的问题,可是我彻底意识到有时因为内存/速度问题须要迭代。 node

所以,在好久之前的某个时候,我去尝试查找是否存在将通用递归方法转换为迭代的任何“模式”或教科书方法,却一无所得。 或至少没有什么我能记住的会有所帮助。 编程

  • 有通常规则吗?
  • 有没有“模式”?

#1楼

递归不过是从另外一个函数调用另外一个函数的过程,只有此过程是经过单独调用一个函数来完成的。 众所周知,当一个函数调用另外一个函数时,第一个函数保存其状态(其变量),而后将控件传递给被调用的函数。 能够经过使用相同的变量名来调用被调用函数,例如fun1(a)能够调用fun2(a)。 当咱们进行递归调用时,没有新的事情发生。 一个函数经过传递相同的类型和类似的名称变量来调用自身(可是很明显,存储在变量中的值是不一样的,只是名称保持不变。)。 可是,在每次调用以前,函数都会保存其状态,而且保存过程将继续。 保存在堆栈上。 函数

如今,堆栈开始播放了。 spa

所以,若是您编写一个迭代程序并每次将状态保存在堆栈上,而后在须要时从堆栈中弹出值,那么您已成功将递归程序转换为迭代程序! rest

证实是简单和分析的。 code

在递归中,计算机维护堆栈,而在迭代版本中,您将必须手动维护堆栈。 递归

考虑一下,只需将深度优先搜索(在图形上)递归程序转换为dfs迭代程序。 内存

祝一切顺利! 开发


#2楼

一般,将堆栈溢出用于递归函数的技术称为蹦床技术,这是Java开发人员普遍采用的技术。 get

可是,对于C#,这里有一个小的辅助方法能够将递归函数变成迭代的,而无需更改逻辑或使代码难以理解。 C#是一种很棒的语言,它可能带来使人惊奇的东西。

它经过使用辅助方法包装方法的某些部分来工做。 例如如下递归函数:

int Sum(int index, int[] array)
{
 //This is the termination condition
 if (int >= array.Length)
 //This is the returning value when termination condition is true
 return 0;

//This is the recursive call
 var sumofrest = Sum(index+1, array);

//This is the work to do with the current item and the
 //result of recursive call
 return array[index]+sumofrest;
}

变成:

int Sum(int[] ar)
{
 return RecursionHelper<int>.CreateSingular(i => i >= ar.Length, i => 0)
 .RecursiveCall((i, rv) => i + 1)
 .Do((i, rv) => ar[i] + rv)
 .Execute(0);
}

#3楼

努力进行递归调用Tail Recursion (递归,其中最后一条语句是递归调用)。 一旦有了这些,将其转换为迭代一般很是容易。


#4楼

在Google上搜索“继续传递样式”。 有一个转换为尾部递归样式的通用过程。 还有将尾递归函数转换为循环的通用过程。


#5楼

要寻找的一种模式是在函数末尾进行递归调用(所谓的尾递归)。 能够轻松地将其替换一下子。 例如,函数foo:

void foo(Node* node)
{
    if(node == NULL)
       return;
    // Do something with node...
    foo(node->left);
    foo(node->right);
}

以对foo的调用结束。 能够替换为:

void foo(Node* node)
{
    while(node != NULL)
    {
        // Do something with node...
        foo(node->left);
        node = node->right;
     }
}

这样就消除了第二个递归调用。

相关文章
相关标签/搜索