十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
递归就是直接或间接的调用自身的函数。下面是用递归方法求fibonacci数列#includestido.hlong fib(int n){if(n==1||n==2)return 1;return fib(n-1)+fib(n-2);} main(){int n;scanf("%d",n);printf("%ld\n",fib(n));return 0;} 说白了就是函数的自身嵌套调用 函数在定义的时候可以调用其他函数,包括自身。 但是一定要有终止条件 否则会进入死循环。上面的终止条件是n==1||n==2
创新互联专注于临西网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供临西营销型网站建设,临西网站制作、临西网页设计、临西网站官网定制、微信平台小程序开发服务,打造临西网络公司原创品牌,更为您提供临西网站排名全网营销落地服务。
...
从汇编的角度来说,函数
返回值
,其实就是函数返回后,cpu中eax的值。在C语言等语方中,在函数中写了返回语句,那么函数在返回时,就会对eax作最后赋值。
int
find(int
a,int
b)
{
if(b=0)
return
100;
else
find(--a,--b);/这里为什么不用返回值?/
}
//为什么不用返回值呢,因为此程序进行递归后,在最初返回时,eax的值被赋值为100,而之后的回溯过程中,程序并没有修改eax的值,所以到最后,返回值还是100。
这种写法是会出问题的。应写成。
int
find(int
a,int
b)
{
if(b=0)
return
100;
else
return
find(--a,--b);
}
为什么了修改之后就出错呢,如以上所说,这很好理解,因为程序最后调用了printf()。eax中的值是printf()的返回值。若把他当成find()的返回值自然是出错了。
以下是执行顺序,没有缩进的表示在f(0)中执行,缩进2个空格的是在f(1)中执行,依次类推,else 中的for循环在 f(1), f(2)中经常会因为if(!used[i])而跳过,只要注意到这一点,就很清楚了!
希望能帮到你..
首先 dep = 0 时,调用 f(0)
执行 else 中的 for 循环(i= 1)
used[1] = true;
a[0] = 1;
进入 dep = 1
执行 else 中的 for 循环(i= 2)
used[2] = true;
a[1] = 2;
进入 dep = 2
执行 else 中的 for 循环,(i=3)
used[3] = true;
a[2] = 3;
进入 dep = 3:
dep=n,执行 if 中的 for 循环开始打印,第一次打印哦!!!!
打印结果 1, 2, 3
返回到dep = 2
used[3] = false;
由于dep=2 的 i = 3,循环结束了,返回到dep = 1
used[2] = false;
dep=1的循环 (i = 3)
used[3] = true;
a[1] = 3;
进入dep=2(循环 i = 2)
used[2] = true;
进入dep=3(打印)
打印结果1, 3, 2
返回到dep = 2
used[2] = false;
返回到 dep = 1
used[3] = false;
返回到dep = 0
used[1] = false;
执行dep=1 中 else 的 for 循环,第二次循环 i= 2
...
返回机制应该在前,弄明白了返回机制递归才好理解
在调用一个函数的时候,编译器先把函数的参数从右自左压入栈中,然后用call指令跳至子过程地址,在跳之前会把当前代码所在的【段:偏移】地址压栈,当子过程执行完,会调用ret指令返回,ret指令和call相反当好是把栈中的【段:偏移】还原回寄存器(cs和ip),ret也就是C++的return关键字(当然,C++因为有重载机制,编译器会在压栈之前给所有的函数作签名改编,这是另一个话题),以上是返回的原理。
弄明白了返回,递归就好理解了,假设从主函数调用一个子函数,这个子函数每次都对参数进行一些处理并递归,那么进入函数体后栈的状态是:参数、返回地址;那么在函数中又调用自己,栈就变成了:参数、返回地址、参数、返回地址;当满足了递归的退出条件时,ret一次,回到前一次自调用的地址,从这个地址开始,处理参数让栈顶停在返回地址处,然后ret......如此往复,直到回到调用子函数的函数体,以上的例子类似于:
void fun(int p)
{
if(p=1)//递归出口
return;
p--;
fun(p);
//这一步编译器实际上会pop ecx然后ret
return;
}