| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1506 人关注过本帖
标题:递归到底怎么想?
只看楼主 加入收藏
dousao
Rank: 2
等 级:论坛游民
帖 子:228
专家分:58
注 册:2007-11-8
结帖率:75%
收藏
 问题点数:0 回复次数:10 
递归到底怎么想?
很麻烦的说。可以把他想象成一个循环还是什么?
如果一个函数递归下还有语句,是不是每递归一次都会执行下一个语句?
比如
fun(n)
{
if(n-1)
  fun(n-1);  //A
printf("sdfsdf");//B
}
如果n是3输出几次sdfsdf?
我一开始理解是在A句时不断的n-1了,一直到n=1的时候也就是n-1=0的时候才执行B句。这肯定是错的。那么就是递归一次执行一次了?
搜索更多相关主题的帖子: 递归 
2007-12-18 15:34
lonmaor
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:郑州
等 级:版主
威 望:75
帖 子:2637
专家分:6423
注 册:2007-11-27
收藏
得分:0 
因为递归就是不断的调用自身,故需要一定的抽象能力,就好像 非programmer 看到 x=x+1 这种等式比较迷茫一样。
简单说,如一个数的阶乘,n!=1*2*3*4*....*n;则
当n>1时,factor(n)=factor(n-1)*n,                //LINE1
当n=1时,factor(1)=1; //这就是递归的终结条件。  //LINE2

由此可写factor的定义为:
int factor(int n)
{
if (n==1)
    return 1;  //即上面的LINE2
else
    return factor(n-1)*n;  //即上面的LINE1
}
2007-12-18 15:46
永夜的极光
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2721
专家分:1
注 册:2007-10-9
收藏
得分:0 
你看你的这个函数,printf在if语句之外,也就是说,只要这个函数被调用,无论if里面的条件是否满足,printf这句都肯定被执行

然后再来看这个函数会被调用多少次
一开始n=3,(调用一次)
然后调用了fun(n-1),也就是fun(2)(调用两次)
fun(2)又调用了fun(n-1),也就是fun(1)(调用3次)
fun(1)不再调用,因为if语句不满足

也就是说,这个函数被调用了3次,所以输出3次

从BFS(Breadth First Study)到DFS(Depth First Study)
2007-12-18 15:55
dousao
Rank: 2
等 级:论坛游民
帖 子:228
专家分:58
注 册:2007-11-8
收藏
得分:0 
袄!是不是只要n被传值他这个函数就从头执行到尾,无论递归函数出现在什么地方都是?
然后在慢慢把递归推出来?大概就是这个意思吧?还要好好理解。
2007-12-18 16:12
lonmaor
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:郑州
等 级:版主
威 望:75
帖 子:2637
专家分:6423
注 册:2007-11-27
收藏
得分:0 
如果没有终止循环的条件,那就是个死循环了。
2007-12-18 16:26
永夜的极光
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2721
专家分:1
注 册:2007-10-9
收藏
得分:0 
递归函数也是一个函数,肯定会根据你结构从头运行到尾,

我一般是这么看递归函数的,
先假设递归的地方总能完成我们指定的任务,然后看这个函数还干了什么其他的事情
然后看有没有能使递归结束的条件,如果有,这个递归就是正确的了
最后如果还是看不出来这个函数的执行顺序,可以假设一个能很快结束的输入值,自己走一遍程序

比如看你写的程序
程序代码:
fun(n)
{
if(n-1)
  fun(n-1);  //A
printf("sdfsdf");//B
}
fun(n-1);  //这一句先不管,反正假设就是调用了其他一个函数,完成了一些功能
那么这整个函数就是剩下一句printf了,而且这句printf肯定会执行到,那么这个函数的功能就很简单了,就是调用另外一个函数,然后输出一句话
现在看递归结束条件(也叫递归出口),每次递归调用,n-1,所以每次调用,传进来的参数都会比上一次小,而且n小到一定程度的时候,就不会再次递归了,那么可以看出这个递归是正确的.
最后要分析一共输出了几次,那么我就假设n=3,自己在脑子里面执行一遍程序,具体过程我3楼说了.
这样,整个递归就分析完了.

你举的这个例子没什么实际意义,可以看2楼的程序
程序代码:
int factor(int n)
{
if (n==1) 
    return 1;  //即上面的LINE2
else
    return factor(n-1)*n;  //即上面的LINE1
}
分析如下:
这个函数是计算阶乘的,如果n=1,那结果为1,如果n>1,那结果怎么算呢?
看这一句return factor(n-1)*n;
factor(n-1)我们不用想这个递归到底执行了什么,先假设它总是可以返回给我(n-1)的阶乘,那我现在要算n的阶乘怎么办?直接乘个n上去不就行了嘛,然后就把结果返回给调用的地方.很好理解吧.
然后看结束条件,每次调用的时候,n-1,所以n每次都变小,而n小到一定程度的时候(n==1),就不会再递归了,也就是说,这个递归是有出口的.
分析到这里其实就够了,如果还是不能理解,那也不要紧,还是假设n=3,我们用脑子当CPU来调用一下这个函数看
一开始n=3,if条件不满足,那程序将返回(2的阶乘*3),但是2的阶乘我们不知道,那就算factor(2)
现在n=2,if还是不满足,程序将返回(1的阶乘*2),但是1的阶乘我们还是不知道,那继续算factor(1)
现在n=1,if满足了,直接返回1,也就是1的阶乘等于1
回到n=2这层,1的阶乘等于1我们终于知道了,那2的阶乘=1的阶乘*2=2我们也就知道了
回到n=3这层,2的阶乘等于2我们也知道了,那3的阶乘=2的阶乘*3=6
结果出来了,factor(3)=6,现在整个函数的流程也就都明白了.

从BFS(Breadth First Study)到DFS(Depth First Study)
2007-12-18 18:19
dousao
Rank: 2
等 级:论坛游民
帖 子:228
专家分:58
注 册:2007-11-8
收藏
得分:0 

万分感谢
有一个用递归存数组的问题.
char ch[81]={0};
fun(int n)
{static int i=0;
         if(n/10)
         fun(n/10);
        ch[i]=n%10+'0';
        i++;
puts(ch);
}
函数的功能就是输入一个整数用字符串形式输出.譬如123
这个存数是怎么存的?从后向前?还是直接从前向后?我单看这个函数感觉是从i=0存的.也就是第一ch[0]=3  ch[1]=2   ch[2]=1
这肯定不对,递归分递和归,意思是说从先从头递到最后,然后从最后归到最前吧?
2007-12-18 19:47
永夜的极光
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2721
专家分:1
注 册:2007-10-9
收藏
得分:0 
递归函数都是从前到后逐层调用,然后从后到前逐层返回

如果你学过数据结构中的"栈",就能很好的理解这种先进后出的结构了

对于上面的程序,要这么看
fun(n)这个函数的功能就是把n转换成对应的字符串,那fun(n/10)就是把n去掉最后一位后的数字变成数组
         if(n/10)
         fun(n/10);
        ch[i]=n%10+'0';
那么看这里,我们不管fun(n/10)是怎么实现的,总之他完成了任务,n的前面几位都存好了,而且这个时候i肯定是指向最后一个字符应该放的地方,那我们只要把n%10+'0'保存到ch[i]就行了
这个时候要再假设我们是递归的中间的某次调用,我们已经把这次该保存的数字保存好了,那么应该为保存下一个数字做好准备工作,所以最后多了一句i++;,使i指向了要保存下一个数字的位置.

至于递归出口很明显了,就不多说

从BFS(Breadth First Study)到DFS(Depth First Study)
2007-12-18 20:26
灭火的风
Rank: 2
来 自:杭州
等 级:论坛游民
帖 子:161
专家分:10
注 册:2006-6-15
收藏
得分:0 
...

void D(int n){ ... }

void C(int n)
{
    if(n-1)
        D(n-1);
    printf("--%d--",n);
}

void B(int n)
{
    if(n-1)
        C(n-1);
    printf("--%d--",n);
}

void A(int n)
{
    if(n-1)
        B(n-1);
    printf("--%d--",n);
}

void func(int n)
{
    if(n-1)
        func(n-1);
    printf("--%d--",n);
}

int main()
{
    A(3);
    func(3);
}

仔细比较一项两种方法都在做些什么,就会明白为什么要递归了
2007-12-19 08:03
yeqishi
Rank: 1
等 级:新手上路
帖 子:69
专家分:0
注 册:2007-9-19
收藏
得分:0 
递归函数逻辑挺好的,可是需要很多堆栈

2007-12-19 12:06
快速回复:递归到底怎么想?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.022174 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved