Download presentation
Presentation is loading. Please wait.
1
5 函数(二) 5.1 基本知识 5.2 函数重载 5.3 示例 5.4 变量的作用域和生命期 5.5 编译预处理 5.6 递归函数
2
1、什么是递归 2、递归函数举例 3、课堂讨论 4、斐波那契(Fibonacci) 数列 5、Hanoi塔问题
3
一个哄小宝宝睡觉前讲的经典故事: 从前有座山,山里有座庙,庙里有个老和尚,在给小和尚讲故事。讲的什么故事呢?从前有座山,山里有座庙,庙里有个老和尚,在给小和尚讲故事。讲什么故事呢?从前有座山,山里有座庙,庙里有个老和尚,在给小和尚讲故事。讲的什么故事呢?从前有座山,山里有座庙,庙里有个老和尚,在给小和尚讲故事。。。。。。
6
1、什么是递归 什么是递归:函数调用了自身(直接递归)。或一个函数调用了另一个函数,而另一个函数却调用了本函数(间接递归)。 从问题求解的角度来看,递归的本质就是将大问题的求解转化为较小问题的求解。持续不断的分解过程最终将问题化简成一个最基本的形式,并且是一个已知解。
7
2、递归函数举例 例:求N! int fact(int n) { if (n==1 || n==0) return 1; else
return n*fact(n-1); }
8
例:求最大公约数的2个版本 int gcd(int a, int b)//递归版 { if(a%b==0) return b; else return gcd(b, a%b); } 迭代法是用计算机解决问题的一种基本方法。它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)进行重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。 int gcd(int a, int b)//迭代版 { while(b!=0){ int t=a%b; a=b; b=t; } return a;
9
3、课堂讨论 问题一:已知每个同学的期中考试成绩,如何求出全班最高分? 方法二? 方法一? 方法三?
10
问题二:如何编程实现ab? 方法二? 二分法 方法一? 常规法 要点: a10 = a5*a5 ; a11 = a5*a5*a
11
4、斐波那契(Fibonacci) 数列 斐波那契(Leonardo Fibonacci,约1170-约1250),意大利数学家,12、13世纪欧洲数学界的代表人物。 他的一个“兔子问题”引起了后人的极大兴趣。题目假定一对大兔子每一个月可以生一对小兔子,而小兔子出生后两个月就有生殖能力,问从一对小兔子开始,n年后能繁殖成多少对兔子?这导致“斐波那契数列”:1,1,2,3,5,8,13,21,…,其规律是每一项(从第3项起)都是前两项的和。
12
问题:求fibonacci数列前40个数。数列第1,2两个数为1,1。从第3个数开始,该数是其前面两个数之和。即:
f1=1 (n=1) f2= (n=2) fn=fn-1+fn (n>2)
13
时间(月) 初生兔子(对) 成熟兔子(对) 兔子总数(对)
若把兔子总数(对)继续写下去,得到的数列便称为斐波那契数列。数列中每个数便是前两个数之和,而数列的最初两个数都是1。 数学上,一般设F0=1, F1=1;当n>1时, Fn=Fn-1+Fn-2 。
14
求解斐波那契数列(迭代法) int fib(int n) { if(n<2) return 1; int f0=1,f1=1,f2;
for(int i=2; i<=n; i++) f2=f0+f1; f0=f1; f1=f2; } return f2; 利用数组保存所有可能的结果,避免每次重新求解可提高效率。 PreProcess(a,40); 结果存入数组a while(cin>>n){ cout<<a[n]<<endl; } int main(){ int n; while(cin>>n){ cout<<fib(n)<<endl; } return 0;
15
求解斐波那契数列(递归法) int fib(int n) { if(n<2) return 1; else
return fib(n-1)+fib(n-2); }
16
知道黄金分割率吗? 当斐波那契数列趋向于无穷大时,相邻两项的比值趋向于黄金分割0.618。
课后建议:百度百科 - 斐波那契数列 课后建议:百度百科 -计算思维
17
斐波那契螺旋线
19
递增的牛群(HLoj 1190) 开始有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?
20
C1=1, C2=2, C3=3, C4=4, C5=6,... 且,当n>3时,Cn = Cn-1 + Cn-3。
时间(年) 小牛 中牛 大牛 总数 数列特点: C1=1, C2=2, C3=3, C4=4, C5=6,... 且,当n>3时,Cn = Cn-1 + Cn-3。
21
求解递增的牛群(递归法) int Cows(int n) { if(n<4) return n; else
return Cows(n-1)+Cows(n-3); }
22
5、 Hanoi塔问题 设A、B、C是三个塔座。开始时,在塔座A上有一叠共n个圆盘,这些圆盘自下而上,由大到小地叠在一起,如后图所示。现在要求将塔座A上的这一叠圆盘移到塔座B上,并仍按同样顺序叠置。在移到圆盘时应遵守以下移动规则: 规则(1):每次只能移动一个圆盘; 规则(2):任何时刻都不允许将较大的圆盘压在较小的圆盘之上; 规则(3):在满足移动规则(1)和(2)的前提下,可将圆盘移至A,B,C中任何一塔座上。
24
问题分析 设an表示从塔座A上的n个圆盘全部转移到另一根柱子上的转移次数。显然,a1 =1。当n≥2时,要将塔座A上的n个圆盘全部转移到塔座B上,可以这样设想: 先把塔座A上的 n-1个圆盘想法转移到塔座C上,这需要转移an-1次,然后把塔座A上的最后一个大圆盘转移到塔座B上,显然这需要转移1次,最后再把塔座C上的 n-1个圆盘转移到塔座B上,这也需要转移an-1 次。经过这些步骤后,所有塔座A上的n个圆盘就全部转移到塔座B上。根据加法规则,一共转移了2an-1 +1次。 可以建立如下的递归关系:
25
计算总的移动次数的递推公式如下 a1=1 an=2an-1+1 (n>1) 求解递推关系式,可得 an=2n-1
26
// 求解hanoi 搬动过程的 参考代码 void move(char get, char put) { cout<<get<<"-->"<<put<<endl; } // 递归函数 void hanoi(int n, char from, char to, char by) if(n==1) move(from,to); else hanoi(n-1,from,by,to); hanoi(n-1,by,to,from); int main() { int n; cin>>n; // move n diskes From A To B By C hanoi(m,'A', 'B', 'C'); return 0; }
27
相关练习题 请使用递归法解决下列问题: 1111 判断回文串 1164 数字和 1190 母牛的故事 5017 最小公倍数
5018 求最大值 5020 求N! 6061 整数转换成字符串 6064 编写递归函数Ack(m,n) 6201 数组程序设计1
Similar presentations