深入理解递归
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果然是名不虚传,高手云集。帖子发上一会儿,各种招数套路纷纷都上来了。高手就是高手啊。虽然解法众多,但最后大家一致肯定的答案是下面这个:
函数只用了一个 return 语句。其中用到了逻辑运算和函数递归。可是高手们有个缺点就是,只给你答案,从不说这是为神马。所以,最后还是得自己去研究。
在分析这段代码前,我们先看看一些简单的递归例子,以便于理解。
求阶乘:
这段代码,学过点C的人肯定都看的懂了。老谭的书上174页有详解。用通俗的说法来讲,fun函数自身的代码用到了自己。这是不是很滑稽,确实,如果没有第6,7行的关键语句,这个代码就真的很无聊了。因为,它会一直运行,调用自己->调用自己…………直到程序的栈存储区溢出崩溃,你可以试一下这个代码
是不是崩溃了!(如果没有,肯定是你的电脑超神了,可以不再看下去了……)回到正题。为了每一次递归调用的现场保护,程序都会将每个中断的现场进行入栈保护,等到递归条件满足返回时,再一个个退栈,恢复现场。为什么要这样做了?其实可以这样理解:
甲,乙,丙,丁四个打入敌人内部的地下党,分别潜伏在不同的区域。甲要得到一个关于敌人城防部署的情报,所以他给已发了消息。由于所处敌区的位置不同,已并未得到这个情报,所以按照约定,已也给他的下一级并丙发出了同样的命令。就这样,消息一级级的传到了丁那里,丁立即做出反应,将情报传给上一级丙……几经周折,最终甲得到了敌人的城防部署,将敌人一网打尽。
这个例子只是很通俗的解释了一下。要理解还得看代码。我们要求n的阶乘,然而根据已知条件:
n=0,1时 n!=1;n>1时,n!=n*(n-1)!;
未完待续………………
闲话休提,言归正传。
这几天,看数据结构的二叉树部分,发现大多数的算法和定义涉及到了递归。特别是遍历,查找,求高度。刚开始看着部分就坐飞机也就是因为这个原因。今天恰好又突然想起了以前遇到的一个经典的关于递归的面试题。所以好好研究了一下函数递归的过程。
题目是:给定一个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)!;
未完待续………………
相关文章推荐
- 【算法-分治】从数组中取出n个元素的所有组合(需要深入理解递归)
- 深入理解递归
- 深入理解递归
- 3. 深入理解递归
- 深入理解Python中的模块、包、递归和正则表达式
- 递归三部曲之深入理解全排列
- 深入理解递归:全排列问题
- 深入理解递归(一)
- 递归和迭代----深入理解递归的使用
- 深入理解递归
- 深入理解递归
- 深入理解递归:全排列问题
- 递归关于内存的深入理解
- 通过河内之塔问题深入理解递归思想
- 深入理解递归
- 深入理解递归以及汉诺塔问题[数据结构]
- 递归三部曲之深入理解斐波那契数列
- 深入理解递归
- C++ Using recursion to process linked list, 深入理解递归的过程(part1)
- java 递归深入理解