ImageVerifierCode 换一换
格式:PPT , 页数:43 ,大小:483KB ,
资源ID:373695      下载积分:2000 积分
快捷下载
登录下载
邮箱/手机:
温馨提示:
如需开发票,请勿充值!快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝扫码支付 微信扫码支付   
注意:如需开发票,请勿充值!
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【http://www.mydoc123.com/d-373695.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(第6章 递归算法.ppt)为本站会员(wealthynice100)主动上传,麦多课文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知麦多课文库(发送邮件至master@mydoc123.com或直接QQ联系客服),我们立即给予删除!

第6章 递归算法.ppt

1、1,第6章 递归算法,递归的概念 递归算法的执行过程 递归算法的设计方法 递归过程和运行时栈 递归算法的效率分析 设计举例,主要知识点,2,存在算法调用自己的情况:,若一个算法直接的或间接的调用自己本身,则称这个算法是递归算法。,(1)问题的定义是递推的,阶乘函数的常见定义是:,6.1递归的概念,3,也可定义为:,写成函数形式,则为:,这种函数定义的方法是用阶乘函数自己本身定义了阶乘函数,称公式(6 3)是阶乘函数的递推定义式。,4,(2)问题的解法存在自调用,一个典型的例子是在有序数组中查找一个数据元素是否存在的折半查找算法。,5,6,6.2递归算法的执行过程,例6-1 给出按照公式6-3计

2、算阶乘函数的递归算法,并给出n = 3时递归算法的执行过程。设计:按照公式6-3计算阶乘函数的递归算法如下:,7,long int Fact(int n) int x;long int y; if(n 0) /n 0时阶乘无定义 printf(“参数错!”);return -1; if(n = 0) return 1;else y = Fact(n - 1); /递归调用return n * y; ,8,设计主函数如下,void main(void) long int fn;fn = Fact(3); ,主函数用实参n= 3调用了递归算法Fact(3),而Fact(3)要通过调用Fact(2)

3、、Fact(2)要通过调用Fact(1)、Fact(1)要通过调用Fact(0)来得出计算结果。Fact(3)的递归调用过程如图6-2所示。,9,图6-2 Fact(3)的递归调用执行过程,10,例6-2 给出在有序数组a中查找数据元素x是否存在的递归算法,并给出如图6-1所示实际数据的递归算法的执行过程。递归算法如下:,11,int BSearch(int a, int x, int low, int high) int mid;if(low high) return -1; /查找不成功 mid = (low + high) / 2;if(x = amid) return mid; /查找

4、成功else if(x amid)return BSearch(a, x, low, mid-1); /在下半区查找elsereturn BSearch(a, x, mid+1, high); /在上半区查找 ,12,测试主函数设计如下: # include main(void) int a = 1, 3, 4, 5, 17, 18, 31, 33; int x = 17;int bn; bn = BSearch(a, x, 0,7);if(bn = -1) printf(“x不在数组a中“);else printf(“x在数组a的下标%d中“, bn); ,13,BSearch(a, x,

5、0,7)的递归调用过程如图6-3所示,其中,实箭头表示函数调用,虚箭头表示函数的返回值。,图6-3 BSearch(a, x, 0,7)的递归调用过程,14,15,6.3递归算法的设计方法,递归算法既是一种有效的算法设计方法,也是一种有效的分析问题的方法。递归算法求解问题的基本思想是:对于一个较为复杂的问题,把原问题分解成若干个相对简单且类同的子问题,这样,原问题就可递推得到解。,16,适宜于用递归算法求解的问题的充分必要条件是:(1)问题具有某种可借用的类同自身的子问题描述的性质;(2)某一有限步的子问题(也称作本原问题)有直接的解存在。当一个问题存在上述两个基本要素时,该问题的递归算法的设

6、计方法是:(1)把对原问题的求解设计成包含有对子问题求解的形式。(2)设计递归出口。,17,例6-3 设计模拟汉诺塔问题求解过程的算法。汉诺塔问题的描述是:设有3根标号为A,B,C的柱子,在A柱上放着n个盘子,每一个都比下面的略小一点,要求把A柱上的盘子全部移到C柱上,移动的规则是:(1)一次只能移动一个盘子;(2)移动过程中大盘子不能放在小盘子上面;(3)在移动过程中盘子可以放在A,B,C的任意一个柱子上。,18,问题分析:可以用递归方法求解n个盘子的汉诺塔问题。基本思想:1个盘子的汉诺塔问题可直接移动。n个盘子的汉诺塔问题可递归表示为,首先把上边的n-1个盘子从A柱移到B柱,然后把最下边的

7、一个盘子从A柱移到C柱,最后把移到B柱的n-1个盘子再移到C柱。4个盘子汉诺塔问题的递归求解示意图如图6-4所示。,19,图6-4 汉诺塔问题的递归求解示意图,20,算法设计:首先,盘子的个数n是必须的一个输入参数,对n个盘子,我们可从上至下依次编号为1,2,n;其次,输入参数还需有3个柱子的代号,我们令3个柱子的参数名分别为fromPeg,auxPeg和toPeg;最后,汉诺塔问题的求解是一个处理过程,因此算法的输出是n个盘子从柱子fromPeg借助柱子auxPeg移动到柱子toPeg的移动步骤,我们设计每一步的移动为屏幕显示如下形式的信息:Move Disk i from Peg X to

8、 Peg Y这样,汉诺塔问题的递归算法可设计如下:,21,void towers(int n, char fromPeg, char toPeg, char auxPeg) if(n=1) /递归出口 printf(“%s%c%s%cn“, “move disk 1 from peg “, fromPeg, “ to peg “, toPeg);return; /把n-1个圆盘从fromPeg借助toPeg移至auxPegtowers(n-1,fromPeg,auxPeg,toPeg); /把圆盘n由fromPeg直接移至toPegprintf(“%s%d%s%c%s%cn“, “move d

9、isk “, n, “ from peg “, fromPeg, “ to peg “, toPeg); /把n-1个圆盘从auxPeg借助fromPeg移至toPegtowers(n-1,auxPeg,toPeg,fromPeg); ,22,测试主函数如下: #include void main(void) Towers(4, A, C, B); 程序运行的输出信息如下:,23,Move Disk 1 from Peg A to Peg B Move Disk 2 from Peg A to Peg C Move Disk 1 from Peg B to Peg C Move Disk 3

10、from Peg A to Peg B Move Disk 1 from Peg C to Peg A Move Disk 2 from Peg C to Peg B Move Disk 1 from Peg A to Peg B Move Disk 4 from Peg A to Peg C Move Disk 1 from Peg B to Peg C Move Disk 2 from Peg B to Peg A Move Disk 1 from Peg C to Peg A Move Disk 3 from Peg B to Peg C Move Disk 1 from Peg A t

11、o Peg B Move Disk 2 from Peg A to Peg C Move Disk 1 from Peg B to Peg C,24,总结如下:递归算法的执行过程是不断地自调用,直到到达递归出口才结束自调用过程;到达递归出口后,递归算法开始按最后调用的过程最先返回的次序返回;返回到最外层的调用语句时递归算法执行过程结束。,25,6.4递归过程和运行时栈,对于非递归函数,调用函数在调用被调用函数前,系统要保存以下两类信息: (1)调用函数的返回地址; (2)调用函数的局部变量值。当执行完被调用函数,返回调用函数前,系统首先要恢复调用函数的局部变量值,然后返回调用函数的返回地址。,

12、26,递归函数被调用时,系统要作的工作和非递归函数被调用时系统要作的工作在形式上类同,但保存信息的方法不同。递归函数被调用时,系统需要一个运行时栈.系统的运行时栈也要保存上述两类信息。每一层递归调用所需保存的信息构成运行时栈的一个工作记录,在每进入下一层递归调用时,系统就建立一个新的工作记录,并把这个工作记录进栈成为运行时栈新的栈顶;每返回一层递归调用,就退栈一个工作记录。因为栈顶的工作记录必定是当前正在运行的递归函数的工作记录,所以栈顶的工作记录也称为活动记录。,27,6.5递归算法的效率分析,斐波那契数列Fib(n)的递推定义是:,求第n项斐波那契数列的递归函数如下:,long Fib(i

13、nt n) if(n = 0 | n = 1) return n; /递归出口else return Fib(n-1) + Fib(n-2); /递归调用 ,28,用归纳法可以证明求Fib(n)的递归调用次数等于2n-1;计算斐波那契数列的递归函数Fib(n)的时间复杂度为O(2n)。计算斐波那契数列Fib(n)问题,我们也可根据公式写出循环方式求解的函数如下:,图6-6 Fib(5)的递归调用树,29,long Fib2(int n) long int oneBack, twoBack, current;int i; if(n = 0 | n = 1) return n;else oneBa

14、ck = 1;twoBack = 0;for(i = 2; i = n; i+) current = oneBack + twoBack;twoBack = oneBack;oneBack = current;return current; ,30,上述循环方式的计算斐波那契数列的函数Fib2(n)的时间复杂度为O(n)。对比循环结构的Fib2(n)和递归结构的Fib(n)可发现,循环结构的Fib2(n)算法在计算第n项的斐波那契数列时保存了当前已经计算得到的第n-1项和第n-2项的斐波那契数列,因此其时间复杂度为O(n);而递归结构的Fib(n)算法在计算第n项的斐波那契数列时,必须首先计算

15、第n-1项和第n-2项的斐波那契数列,而某次递归计算得出的斐波那契数列,如Fib(n-1)、Fib(n-2)等无法保存,下一次要用到时还需要重新递归计算,因此其时间复杂度为O(2n) 。,31,6.6递归算法到非递归算法的转换,有些问题需要用低级程序设计语言来实现,而低级程序设计语言(如汇编语言)一般不支持递归,此时需要采用问题的非递归结构算法。一般来说,存在如下两种情况的递归算法。(1)存在不借助堆栈的循环结构的非递归算法,如阶乘计算问题、斐波那契数列的计算问题、折半查找问题等。这种情况,可以直接选用循环结构的算法。,32,(2)存在借助堆栈的循环结构的非递归算法,所有递归算法都可以借助堆栈

16、转换成循环结构的非递归算法,如下边例6-4设计的汉诺塔问题的借助堆栈的循环结构的非递归算法。此时可以把递归算法转换成相应的非递归算法,有两种转换方法:一种方法是借助堆栈,用非递归算法形式化模拟递归算法的执行过程;另一种方法是根据要求解问题的特点,设计借助堆栈的循环结构算法。这两种方法都需要使用堆栈,这是因为堆栈的后进先出特点正好和递归函数的运行特点相吻合。下面讨论的例6-4是第二种情况下的第一种转换方法的例子,33,6.7设计举例,6.7.1 一般递归算法设计举例,例6-5 设计一个输出如下形式数值的递归算法。n n n . n3 3 3 2 21,34,问题分析:该问题可以看成由两部分组成:

17、一部分是输出一行值为n的数值;另一部分是原问题的子问题,其参数为n-1。当参数减到0时不再输出任何数据值,因此递归的出口是当参数n0时空语句返回。,算法设计:递归算法设计如下:void Display(int n) int i; for(i = 1; i 0) Display(n - 1); /递归 /n=0为递归出口,递归出口为空语句,35,例6-6 设计求解委员会问题的算法。委员会问题是:从一个有n个人的团体中抽出k (kn)个人组成一个委员会,计算共有多少种构成方法。问题分析:从n个人中抽出k(kn)个人的问题是一个组合问题。把n个人固定位置后,从n个人中抽出k个人的问题可分解为两部分之

18、和:第一部分是第一个人包括在k个人中,第二部分是第一个人不包括在k个人中。对于第一部分,则问题简化为从n-1个人中抽出k-1个人的问题;对于第二部分,则问题简化为从n-1个人中抽出k个人的问题。图6-7给出了n=5, k=2时问题的分解示意图。,36,图6-7 委员会问题分解示意图,37,当n=k或k=0时,该问题可直接求解,数值均为1,这是算法的递归出口。因此,委员会问题的递推定义式为:,38,int Comm(int n, int k) if(n n) return 0; if(k = 0) return 1; if(n = k) return 1; return Comm(n-1, k-

19、1) + Comm(n-1, k); ,39,例6-7 求两个正整数n和m最大公约数的递推定义式为:,要求:(1)编写求解该问题的递归算法;(2)分析当调用语句为Gcd(30, 4)时算法的执行过程和执行结果;(3)分析当调用语句为Gcd(97, 5)时算法的执行过程和执行结果;(4)编写求解该问题的循环结构算法。,40,解:(1)递归算法如下:int Gcd(int n, int m) if(n n) return Gcd(m, n);else return Gcd(m, n % m);,41,(2)调用语句为Gcd(30, 4)时,因mn,递归调用Gcd(97, 5);因mn,递归调用Gc

20、d(5, 2);因mn,递归调用Gcd(2, 1);因mn,递归调用Gcd(1, 0);因m=0,到达递归出口,函数最终返回值为n=1,即5和97的最大公约数为1。,42,6.7.2 回溯法及其设计举例,回溯法是递归算法的一种特殊形式,回溯法的基本思想是:对一个包括有很多结点,每个结点有若干个搜索分支的问题,把原问题分解为对若干个子问题求解的算法。当搜索到某个结点、发现无法再继续搜索下去时,就让搜索过程回溯退到该结点的前一结点,继续搜索这个结点的其他尚未搜索过的分支;如果发现这个结点也无法再继续搜索下去时,就让搜索过程回溯(即退回)到这个结点的前一结点继续这样的搜索过程;这样的搜索过程一直进行到搜索到问题的解或搜索完了全部可搜索分支没有解存在为止。,43,习题6-6,6-8 ,6-9习题6-10,6-12 ,6-15,作业,

copyright@ 2008-2019 麦多课文库(www.mydoc123.com)网站版权所有
备案/许可证编号:苏ICP备17064731号-1