void print(int p)
{
if (p==0)
{
return;
}
print(p-1);
cout<<p;
return;
}
这是一个基本功能,可根据您输入的数字计算,因此如果您发送6,则打印123456.
我一直盯着这看半个小时,我无法弄清楚它是如何运作的。为什么递归调用print(p-1);
只是导致语句if(p==0)
并且在到达cout<<p
之前返回?
cout<<p
如何访问?我完全理解在递归调用之前放置cout<<p;
时它是如何工作的,而是像654321那样打印。
答案 0 :(得分:4)
您似乎认为return
总是返回到main(或者您调用print的地方),和/或递归调用替换自身。这不是真的。
如果您致电print(6)
,则会以if
开头,然后继续print(p-1);
。此时,print(5)
的调用已启动,但stil之前存在print(6)
并等待print(5)
完成。
print(5)
正在执行相同操作,导致调用print(4)
,print(5)
等待print(4)
。等等...
在某些时候,print(1)
会调用print(0)
,而if
会在调用另一个print
之前立即结束该功能。现在,当print(0)
结束时,print(1)
会继续使用其代码,即cout
。在此之后,print(1)
结束,导致print(2)
继续其工作,依此类推......
最后,当print(5)
结束时,最顶层的嵌套调用(print(6)
)会继续,并且在cout
之后,它可以返回到main(或从哪里)否则它被称为。)
答案 1 :(得分:3)
递归调用就像stack一样。如果我们尝试通过将您的调用扩展为print
并将p
替换为其值来实现可视化,我们会得到以下内容:
print(4)
{
if (4==0)
return;
print(3)
{
if (3==0)
return;
print(2)
{
if (2==0)
return;
print(1)
{
if (1==0)
return;
print(0)
{
if (0==0)
return; // This return is called
print(-1) // Line skipped
cout<<0; // Line skipped
return; // Line skipped
}
cout<<1;
return;
}
cout<<2;
return;
}
cout<<3;
return;
}
cout<<4;
return;
}
请注意,return
语句只保留当前版本的print
,这是堆栈中的当前函数。这意味着我们最终会一直走回创建的堆栈。
答案 2 :(得分:1)
虽然还有其他答案并且它们都是正确的,但我会尝试解释一些其他问题。在C ++中使用这种类型的递归仅用于学术目的,但是像LISP这样的语言没有循环并依赖于递归。
在递归函数中,需要考虑三个关键要素:
例如。如果你这样做:
if(p<=0)
return;
print(p-1);
cout << p;
您的打印顺序与以下相反:
if(p<=0)
return;
cout << p;
print(p-1);
如果您首先递归然后再打印,那么您使用的是深度优先策略。递归将继续,直到满足 end 条件,然后将完成打印。所以第一次打印将是更接近 end 条件的打印;然后是下一个;等等。你可以弄清楚在另一种情况下会发生什么。
值得注意的是,每次递归时,某种堆栈(顺便说一下,以LIFO顺序工作)都必须保持所有先前递归的状态。当您的问题需要大量递归时,您最终可能会使用所有可用资源。因此,在像C ++这样的语言中,最好使用一个只保留一个 state 的循环。
然而,当您必须解决某些问题时,递归会很方便。我想到的是解析表达式,其中某些位具有与某些位不同的优先级。像1+2*3
一样。在这种情况下,应首先评估2*3
,然后将结果添加1+6
以产生7
。这称为递归下降解析器。
答案 3 :(得分:0)
想想print(1)
:它传递if语句,然后调用print(0)
;返回时,通过调用print(1)
继续调用cout
。