递归的逻辑是啥
Posted
技术标签:
【中文标题】递归的逻辑是啥【英文标题】:What is the logic of the recursion递归的逻辑是什么 【发布时间】:2015-08-06 06:16:59 【问题描述】:这是我使用递归的阶乘代码。
class Factorial
public static void main(String args[])
Factorial f = new Factorial();
System.out.println(f.fact(Integer.parseInt(args[0])));
private int fact(int num)
int result;
if(num == 1)
return 1;
result = fact(num - 1) * num;
return result;
现在运行这个程序,我这样做了
D:\>java Factorial 3
现在按照进入fact函数的逻辑,其中num = 3,所以会跳转到
result = fact(num - 1) * num;
这里会变成
result = fact(3 - 1) * num;
即result = fact(2) * num;
在这一步中,我有点困惑它是否执行整个步骤,即
result = fact(num - 1) * num;
或者只是fact(num - 1)
按照逻辑,它应该做的就是调用fact函数。因此,程序的控制再次到达了 num = 2 的事实函数的开头。它会再次跳到
result = fact(num - 1) * num;
所以,它会变成
result = fact(2 - 1) * num;
即result = fact(1) * num;
现在,它应该再次调用 fact 函数而不执行整个语法 & 再次到达 fact 方法的开头 num = 1。这一次将匹配 num == 1 并返回 1。现在它会返回到
result = fact(num - 1) * num;
所以,它会变成
result = fact(1 - 1) * num;
即result = fact(0) * num;
现在接下来会发生什么?
我走对了吗?如果不是,那将是什么更正?
我不太清楚这个递归程序的流程。
【问题讨论】:
您是否尝试过在调试器中执行此操作并查看调用堆栈?老实说,您并不清楚您在问什么。for num = 2 [..] So, it will become result = fact(1 - 1) * num;
你为什么会这样想?
在每个步骤中它执行fact(num - 1)
并通过再次调用相同的方法向前移动,但在最后一步控制向后移动以完成方法体
没有地方只计算fact(num - 1)
而不乘以num
任何体面的调试器都可以做到这一点。免费下载 Eclipse 并以这种方式逐步执行代码...
【参考方案1】:
所以,它会变成
result = fact(1 - 1) * num;
不。对于num = 2
,
result = fact(num - 1) * num;
变成
result = 1 * num; // i.e. 1 * 2
fact
返回一个值,这意味着必须将整个调用替换为该值。
不知道为什么你甚至会认为num
会发生变化。您的代码中没有 num = ...
。
【讨论】:
【参考方案2】:我在程序中添加了一些跟踪。执行它并查看输出。应该很容易理解。
package snippet;
class Factorial
public static void main(String args[])
Factorial f = new Factorial();
System.out.println(f.fact(Integer.parseInt("5")));
private int fact(int num)
int result;
if (num == 1)
return 1;
result = fact(num - 1) * num;
System.out.println("fact(" + num + ") = " + result + " = fact(" + (num - 1) + ") * " + num);
return result;
事实(2) = 2 = 事实(1) * 2 事实(3) = 6 = 事实(2) * 3 事实(4) = 24 = 事实(3) * 4 事实(5) = 120 = 事实(4) * 5 120
【讨论】:
【参考方案3】:您的逻辑是正确的,但您犯了 3 个基本错误。 如果我们以你为例; 首先你运行程序
D:\>java Factorial 3
那么您就有了第一个错误,因为根据逻辑,所有“num”都必须替换为“3”。所以你得到:
result = fact(3 - 1) * 3;
即:
result = fact(2)*3;
那么我们有第二个错误,因为根据fact(num)的定义,
fact(2) = fact(2-1)*2
所以我们实际上有
result = (fact(2-1)*2)*3
在
中评估result = (fact(1)*2)*3
这里是第三个错误,因为再次根据 fact(num) 定义:fact(1) = 1
而不是fact(1) = fact(1-1)*1
所以我们终于有了:
result = ((1)*2)*3
更明确地说,如果您遵循调试器中的所有调用顺序,您将得到类似这样的内容(我将变量的值放在括号中):
private int fact(num3)
int result;
if(num3== 1)
return 1;
result = fact(num3 - 1) * num3;
private int fact(num3-1)
int result;
if(num3-1== 1)
result = fact(num3-1 - 1) * num3-1;
private int fact(num3-1-1)
int result;
if(num3-1-1== 1)
return 1;
return result1*3-1;
return result1*3-1*3;
【讨论】:
【参考方案4】:除非我们达到停止条件:
fact(num) = fact(num - 1) * num;
因此:
fact(3) = fact(3 - 1) * 3;
记住 fact(1) = 1(来自 fact()
方法早期的 if 语句):
fact(3) = fact(2) * 3;
fact(2) = fact(1) * 2;
fact(1) = 1;
替换每个元素:
fact(3) = 1 * 2 * 3;
递归用于反复深入进程,直到遇到停止条件 - 在这种情况下,当 num = 1 时。
【讨论】:
【参考方案5】:调用 f.fact(3) 正在通过以下步骤扩展:
1. result = fact(3 - 1) * 3 = fact(2) * 3
2. result = (fact(2 - 1) * 2) * 3 = (fact(1) * 2) * 3
3. result = 1 * 2 * 3 because fact(1) returns 1.
【讨论】:
【参考方案6】:您的实现是正确的,但它永远不会达到fact(1-1) * 1
状态,因为您从if(num == 1)
的方法返回。
num
变量仅限于方法参数的范围。因此,每次调用fact
方法num
变量都会被分配一个新值(即num-1),并且仅限于该参数范围。所以当fact(num-1)
返回时,num 的值将是原始值,而不是num-1
。
【讨论】:
【参考方案7】:你的例子流程是这样的 步骤 1. 事实(3)*3; //调用num值为3的函数 步骤 2. 事实(2)*2; //再次使用 num=2 调用 fact() 方法 步骤 3. 事实(1)*1; //现在将匹配 num == 1 并返回 1。 一世。例如, 1 * 1 = 1; //现在,将分别执行步骤 2 和 1 第 2 步。1 * 2 = 2; 第 1 步。2 * 3 = 6;
所以,最终答案将是 6注意:在第 3 步中,值是 返回,所以它不会再调用 this result = fact(0) * num; //你提到的问题。
【讨论】:
以上是关于递归的逻辑是啥的主要内容,如果未能解决你的问题,请参考以下文章