我的问题是关于递归,我很难理解一点。我调试了一小段代码,我知道流程是如何工作的,但是问为什么以及如何?我会解释我的怀疑。
我知道这可能是一个愚蠢的问题,但请清楚我。
检查代码 - :
#include <stdio.h>
void sum(int n);
void add(int number);
int main()
{
int number, result;
printf("Enter a positive integer: ");
scanf("%d", &number);
sum(number);
}
void sum(int num)
{
if (num!=0) {
sum(num - 1); //(2-1) (1-1)
sum(num - 1); // (1-1) (2-1)
add(num);
}
}
void add(int number){
int a = 5;
int c = 0;
c = a+number;
printf("%d ",c);
}
当我给用户输入2时,流程转到if
条件 - > Valiadte - >进入内部 - >首先调用sum
(2-1) - >再次上升 - >验证 - >首先调用sum
(1-1) - >离开if
- >调用第二个sum
(1-1) - >走出if
- >调用add
函数 - >再次调用sum
(2-1) - >验证if
- >调用第一个sum
(1-1 ) - >出去 - >再次调用第二个sum
(1-1) - >调用add
- >退出。
Recursion
定义说 - :当函数调用自身时它是递归的,递归继续,直到满足某些条件来阻止它。
我的问题是为什么第二笔被称为2次或更多次?我的意思是,如果你看到它在第一次调用时条件(1-1)
,所以它应该退出并且只是调用add,但是在调用add
之后它再次用于(2-1)
。第二个Sum
是否以相反的顺序被调用?
是不是如果首先被称为123
然后第二个必须去321
甚至在它满足条件后?这是递归过程实际上如何工作?谁能解释这个概念?
我的问题稍微更新一下。我删除了第二个内部函数调用,现在剩下一个内部递归函数。检查更新的代码 - :
void sum(int num)
{
if (num != 0) {
sum(num - 1);
}
if (num==2) {
printf("Back to memory address of 2 , you can exit out of function now ");
}
}
Input = sum(2)
。现在当sum
gosum(1-1)
或sum(0)
- >退出if。我看到电话没有结束功能。 num
的值再次回到2
go(0->1>2)
- >进入if (num==2)
- >在控制台上打印 - >退出功能。
这表明了什么?如果我做出一个猜测就像 - :内部调用作为pass by value
而不是reference
?因此,甚至内部递归函数更新num
的值它不会改变memory address
仍然是2
的值。
流程是这样的 - :
sum(2)
实际内存地址值 - > sum(1)
复制值 - > sum(0)
复制值。好的,我现在可以出去了。
可是等等!!我无法退出功能,num
必须返回并更新实际内存地址值 - :
num = 0 , num=1 , num=2(That's what I was looking for )
。大!!没有功能。
那是怎么回事?我还是有点卡住了。
添加一些简单的printf
语句并跟踪全局depth
变量中的“调用深度”,可以很好地表示正在发生的事情:
int depth = 0;
void sum(int num)
{
for(int i = 0; i < depth; ++i) printf("\t");
printf("-> sum | depth: %d | num: %d\n", depth, num);
++depth;
if (num != 0) {
sum(num - 1);
sum(num - 1);
add(num);
}
--depth;
}
输入2
:
-> sum | depth: 0 | num: 2
-> sum | depth: 1 | num: 1
-> sum | depth: 2 | num: 0
-> sum | depth: 2 | num: 0
add: 6
-> sum | depth: 1 | num: 1
-> sum | depth: 2 | num: 0
-> sum | depth: 2 | num: 0
add: 6
add: 7
你也可以在sum
的末尾打印,看看退出函数的时间:
-> sum | depth: 0 | num: 2
-> sum | depth: 1 | num: 1
-> sum | depth: 2 | num: 0
<- sum | depth: 2 | num: 0
-> sum | depth: 2 | num: 0
<- sum | depth: 2 | num: 0
add: 6
<- sum | depth: 1 | num: 1
-> sum | depth: 1 | num: 1
-> sum | depth: 2 | num: 0
<- sum | depth: 2 | num: 0
-> sum | depth: 2 | num: 0
<- sum | depth: 2 | num: 0
add: 6
<- sum | depth: 1 | num: 1
add: 7
<- sum | depth: 0 | num: 2
这是因为您不修改该值
void sum(int num)
{
if (num!=0) {
sum(num - 1); //(2-1) (1-1) mark this as call [a]
sum(num - 1); // (1-1) (2-1) mark this as call [b]
add(num);
}
}
当你打电话给sum(2)时:
正如你所知,sum永远不会终止(如果你摆脱了第二次递归调用),输入为2,调用序列是:调用sum与2 if if计算为true所以第一个sum用参数调用1 if再次为true所以第一个sum现在被调用,参数为0,if if计算为false所以现在第二个和被调用参数-1第一个如果求值为true所以第一个和被调用参数为-2首先,如果计算结果为true,则第一个总和用-3来调用。我真的不明白你为什么要第二次打电话。