您的位置:首页 > 其它

深入理解递归

2011-12-04 22:38 141 查看
这学期学数据结构,这个女老师很要命,按同学的说法是常常自己把自己推翻了。讲课从来不按常理出牌,按老湿的说法是,4个2把俩王代出去了,一上来就是高潮,没有一点点逻辑……晕死…… 还好,自己还有一点自学能力,不然就真给她给悲催了。

闲话休提,言归正传。

这几天,看数据结构的二叉树部分,发现大多数的算法和定义涉及到了递归。特别是遍历,查找,求高度。刚开始看着部分就坐飞机也就是因为这个原因。今天恰好又突然想起了以前遇到的一个经典的关于递归的面试题。所以好好研究了一下函数递归的过程。

题目是:给定一个0~9到的自然数n,编写函数print()输出0~n的各个数字和其逆序。如: 给定n为 9,输出为: 0 1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1 0。

要求:不许用,循环,分支,判断等语句。print()参数自定。函数内只允许有一个语句。

当时看到这题,觉得这货很变态。不是坑爹嘛,不用循环,分支,判断就算了,还只让有一个语句。

无赖中,只有去CSDN请教高手。CSDN果然是名不虚传,高手云集。帖子发上一会儿,各种招数套路纷纷都上来了。高手就是高手啊。虽然解法众多,但最后大家一致肯定的答案是下面这个:

#include<iostream>
using namespace std;

int print(int a,int b)
{
return cout<<a && (a >= b || print(a + 1, b)) && (a >= b ||(cout<<a));
}

int main()
{
int a=0,b=9;
print(a,b);
return 0;
}


函数只用了一个 return 语句。其中用到了逻辑运算和函数递归。可是高手们有个缺点就是,只给你答案,从不说这是为神马。所以,最后还是得自己去研究。

在分析这段代码前,我们先看看一些简单的递归例子,以便于理解。

求阶乘:

#include<iostream>
using namespace std;

int fun(int n)
{
if(n==1||n==0)
return 1;
else
return n*fun(n-1);
}
int main()
{
cout<<fun(3)<<endl;
return 0;
}


这段代码,学过点C的人肯定都看的懂了。老谭的书上174页有详解。用通俗的说法来讲,fun函数自身的代码用到了自己。这是不是很滑稽,确实,如果没有第6,7行的关键语句,这个代码就真的很无聊了。因为,它会一直运行,调用自己->调用自己…………直到程序的栈存储区溢出崩溃,你可以试一下这个代码

void fun(int n)
{
fun(n-1);
}

int main()
{
fun(3);
return 0;
}


是不是崩溃了!(如果没有,肯定是你的电脑超神了,可以不再看下去了……)回到正题。为了每一次递归调用的现场保护,程序都会将每个中断的现场进行入栈保护,等到递归条件满足返回时,再一个个退栈,恢复现场。为什么要这样做了?其实可以这样理解:

甲,乙,丙,丁四个打入敌人内部的地下党,分别潜伏在不同的区域。甲要得到一个关于敌人城防部署的情报,所以他给已发了消息。由于所处敌区的位置不同,已并未得到这个情报,所以按照约定,已也给他的下一级并丙发出了同样的命令。就这样,消息一级级的传到了丁那里,丁立即做出反应,将情报传给上一级丙……几经周折,最终甲得到了敌人的城防部署,将敌人一网打尽。

这个例子只是很通俗的解释了一下。要理解还得看代码。我们要求n的阶乘,然而根据已知条件:

n=0,1时 n!=1;n>1时,n!=n*(n-1)!;

未完待续………………
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: