将while / for循环转换为递归背后的大创意/策略?转换何时可能/不可能?

时间:2013-06-28 19:38:22

标签: recursion

我一直在编写(不复杂的)代码,我觉得我对while和for循环以及if / else语句有一定的把握。我还应该说,我觉得我(至少在我的层面上)了解递归的概念。也就是说,我理解一个方法如何一直调用自己,直到迭代的参数与方法中的基本情况匹配,此时方法开始终止并将控制(连同值)传递给先前的实例,最终总体值为确定第一个电话。我可能没有很好地解释它,但我认为我理解它,我可以跟踪/记录我见过的结构化例子。但我的问题是在野外创建递归方法,即在非结构化的情况下。

我们的教授希望我们在每次机会时递归编写,并且(在技术上不准确?)声明所有循环都可以用递归替换。但是,由于很多时候递归操作包含在while或for循环中,这意味着,要说明显而易见的,不是每个循环都可以用递归替换。所以......

对于非结构化/非课堂情况,

1)我怎样才能认识到循环情况可以/不能变成递归,

2)将递归应用于某种情况时,使用的总体思路/策略是什么?我的意思是,我该如何处理这个问题呢?该问题的哪些方面将用作递归标准等?

谢谢!

编辑6/29:

虽然我很欣赏这两个答案,但我想也许我的问题的序言太长了,因为它似乎得到了所有人的关注。我真正要求的是有人与我分享,一个在循环中“思考”的人,一种实现递归解决方案的方法。 (出于问题的目的,请假设我对解决方案有足够的了解,但只需要创建递归代码。)换句话说,要应用递归解决方案,我在问题/解决方案中寻找什么,我将然后用于递归?也许一些关于应用递归的非常一般的陈述也会有所帮助。 (注意:请,不是递归的定义,因为我觉得我非常理解这个定义。这只是我要问的应用它们的过程。)谢谢!

3 个答案:

答案 0 :(得分:4)

每个循环都可以很容易地变成递归。 (每次递归都可以转化为循环,但并不总是很容易。)

但是,我意识到,如果你不知道怎么说“相当容易”并不是非常有用,所以这就是这个想法:

对于这个解释,我将假设一个普通的vanilla循环 - 没有嵌套循环或for循环,没有突破循环的中间,没有从循环的中间返回,等等。事情也可以处理,但会使解释变得混乱。

简单的vanilla while循环可能如下所示:

1. x = initial value;
2. while (some condition on x) {
3.     do something with x;
4.     x = next value;
5. }
6. final action;

然后递归版本将是

A. def Recursive(x) {
B.     if (some condition on x) {
C.         do something with x;
D.         Recursive(next value);
E.     }
F.     else { # base case = where the recursion stops
G.         final action;
H.     }
I.
J. Recursive(initial value);

所以,

  • 第1行中x的初始值成为第J行上的Recursive的orginial参数
  • 第2行的循环条件成为行B上的if的条件
  • 第3行循环内的第一个动作成为if行C中的第一个动作
  • 第4行的x的下一个值成为第D行的递归的下一个参数
  • 第6行的最终动作成为G行基本案例中的行动

如果在循环中更新了多个变量,那么在递归函数中通常会有相应数量的参数。

同样,这个基本配方可以被修改以处理比普通香草环路更漂亮的情况。

次要注释:在递归函数中,将基本案例放在if的“then”侧而不是“else”侧更常见。在这种情况下,您可以将if的条件翻转到相反的位置。也就是说,while循环中的条件测试何时继续运行,而递归函数中的条件测试何时停止。

答案 1 :(得分:2)

  

我可能没有很好地解释它,但我想我理解它,我可以跟踪/记录我见过的结构化例子

这很酷,如果我理解你的解释,那么乍看之下你认为递归的工作原理是正确的。

  

我们的教授希望我们在每个机会都递归写一下,并且做出了(技术上不准确?)语句,所有循环都可以用递归替换

这不是不准确的。这是事实。反过来也是可能的:每次使用递归函数时,都可以使用迭代重写。 可能很难且不直观(如穿越树),但这是可能的。

  

如何识别循环可以/不能变成递归

简单:

enter image description here

  

进行转换时使用的整体构思/策略是什么?

不幸的是,没有这样的事情。而且我的意思是没有普遍的或一般的“全力以赴”的方法,你必须专门考虑在解决特定问题时考虑每个案例。但是,有一件事可能会有所帮助。当从迭代算法转换为递归算法时,请考虑模式。只有少量差异才能重复自身的部分的确切时间和位置在哪里?

此外,如果您希望将递归算法转换为迭代算法,请考虑在硬件级别实现递归的绝大多数方法是使用(调用)堆栈。除了解决可转换算法(例如心爱的因子或Fibonacci函数)时,您总是可以考虑它在汇编程序中的外观,并创建一个显式堆栈。很脏,但有效。

答案 2 :(得分:0)

for(int i = 0; i < 50; i++) 
{
    for(int j = 0; j < 60; j++)
    {
    }
}

等于:

rec1(int i)
{
    if(i < 50)
        return;
    rec2(0);
    rec1(i+1);
}

rec2(int j)
{
    if(j < 60)
        return;
    rec2(j + 1);
}

每个循环都可以递归。相信你的教授,他是对的!