版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、数据结构C语言版-第06章1 第第6 6章章 递归算法递归算法 递归的概念递归的概念 递归算法的执行过程递归算法的执行过程 递归算法的设计方法递归算法的设计方法 递归过程和运行时栈递归过程和运行时栈 递归算法的效率分析递归算法的效率分析 设计举例设计举例 主要知识点主要知识点 数据结构C语言版-第06章2 存在算法调用自己的情况:存在算法调用自己的情况: 若一个算法直接的或间接的调用自己本身,则称这若一个算法直接的或间接的调用自己本身,则称这 个算法是递归算法。个算法是递归算法。 (1 1)问题的定义是递推的)问题的定义是递推的 阶乘函数的阶乘函数的常见定义常见定义是:是: 6.16.1递归的
2、概念递归的概念 数据结构C语言版-第06章3 也可定义为:也可定义为: 写成函数形式,则为:写成函数形式,则为: 这种函数定义的方法是用阶乘函数自己本身定义了阶这种函数定义的方法是用阶乘函数自己本身定义了阶 乘函数,称公式(乘函数,称公式(6 3)是阶乘函数的)是阶乘函数的递推定义式递推定义式。 数据结构C语言版-第06章4 (2)问题的解法存在自调用)问题的解法存在自调用 一个典型的例子是在有序数组中查找一个数据元素是否一个典型的例子是在有序数组中查找一个数据元素是否 存在的存在的折半查找算法折半查找算法。 数据结构C语言版-第06章5 图图6-1 6-1 折半查找过程折半查找过程 数据结构
3、C语言版-第06章6 6.26.2递归算法的执行过程递归算法的执行过程 例例6-1 6-1 给出按照公式给出按照公式6-36-3计算阶乘函数的递归算法,计算阶乘函数的递归算法, 并给出并给出n = 3n = 3时递归算法的执行过程。时递归算法的执行过程。 设计:按照公式设计:按照公式6-36-3计算阶乘函数的递归算法如下:计算阶乘函数的递归算法如下: 数据结构C语言版-第06章7 long int Fact(int n) int x; long int y; if(n 0) /n high) return -1;/查找不成功查找不成功 mid = (low + high) / 2; if(x
4、= amid) return mid;/查找成功查找成功 else if(x amid) return BSearch(a, x, low, mid-1);/在下半区查找在下半区查找 else return BSearch(a, x, mid+1, high);/在上半区查找在上半区查找 数据结构C语言版-第06章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) prin
5、tf(x不在数组不在数组a中中); else printf(x在数组在数组a的下标的下标%d中中, bn); 数据结构C语言版-第06章13 BSearch(a, x, 0,7)BSearch(a, x, 0,7)的递归调用过程如图的递归调用过程如图6-36-3所示,所示, 其中,实箭头表示函数调用,虚箭头表示函数的返回值。其中,实箭头表示函数调用,虚箭头表示函数的返回值。 图图6-3 BSearch(a, x, 0,7)6-3 BSearch(a, x, 0,7)的递归调用过程的递归调用过程 数据结构C语言版-第06章14 数据结构C语言版-第06章15 6.36.3递归算法的设计方法递归算
6、法的设计方法 递归算法既是一种有效的算法设计方法,也是一种有效的递归算法既是一种有效的算法设计方法,也是一种有效的 分析问题的方法。分析问题的方法。 递归算法求解问题的基本思想是:对于一个较为复杂的问递归算法求解问题的基本思想是:对于一个较为复杂的问 题,把原问题分解成若干个相对简单且类同的子问题题,把原问题分解成若干个相对简单且类同的子问题, ,这样,原这样,原 问题就可递推得到解。问题就可递推得到解。 数据结构C语言版-第06章16 适宜于用递归算法求解的问题的充分必要条件是:适宜于用递归算法求解的问题的充分必要条件是: (1 1)问题具有某种可借用的类同自身的子问题描述的性)问题具有某种
7、可借用的类同自身的子问题描述的性 质;质; (2 2)某一有限步的子问题(也称作本原问题)有直接的)某一有限步的子问题(也称作本原问题)有直接的 解存在。解存在。 当一个问题存在上述两个基本要素时,该问题的递归算当一个问题存在上述两个基本要素时,该问题的递归算 法的设计方法是:法的设计方法是: (1 1)把对原问题的求解设计成包含有对子问题求解的形)把对原问题的求解设计成包含有对子问题求解的形 式。式。 (2 2)设计递归出口。)设计递归出口。 数据结构C语言版-第06章17 例例6-3 6-3 设计模拟汉诺塔问题求解过程的算法。汉诺塔问题的设计模拟汉诺塔问题求解过程的算法。汉诺塔问题的 描述
8、是:设有描述是:设有3 3根标号为根标号为A A,B B,C C的柱子,在的柱子,在A A柱上放着柱上放着n n个盘子,个盘子, 每一个都比下面的略小一点,要求把每一个都比下面的略小一点,要求把A A柱上的盘子全部移到柱上的盘子全部移到C C柱柱 上,移动的规则是:上,移动的规则是: (1 1)一次只能移动一个盘子;)一次只能移动一个盘子; (2 2)移动过程中大盘子不能放在小盘子上面;)移动过程中大盘子不能放在小盘子上面; (3 3)在移动过程中盘子可以放在)在移动过程中盘子可以放在A A,B B,C C的任意一个柱子的任意一个柱子 上。上。 数据结构C语言版-第06章18 问题分析:问题分
9、析: 可以用递归方法求解可以用递归方法求解n n个盘子的汉诺塔问题。个盘子的汉诺塔问题。 基本思想:基本思想: 1 1个盘子的汉诺塔问题可直接移动。个盘子的汉诺塔问题可直接移动。n n个盘子的汉个盘子的汉 诺塔问题可递归表示为,首先把上边的诺塔问题可递归表示为,首先把上边的n-1n-1个盘子从个盘子从A A柱柱 移到移到B B柱,然后把最下边的一个盘子从柱,然后把最下边的一个盘子从A A柱移到柱移到C C柱,最后柱,最后 把移到把移到B B柱的柱的n-1n-1个盘子再移到个盘子再移到C C柱。柱。4 4个盘子汉诺塔问题个盘子汉诺塔问题 的递归求解示意图如图的递归求解示意图如图6-46-4所示。
10、所示。 数据结构C语言版-第06章19 图图6-4 6-4 汉诺塔问题的递归求解示意图汉诺塔问题的递归求解示意图 数据结构C语言版-第06章20 算法设计:首先,盘子的个数算法设计:首先,盘子的个数n n是必须的一个输入参数,是必须的一个输入参数, 对对n n个盘子个盘子, ,我们可从上至下依次编号为我们可从上至下依次编号为1,2,n1,2,n;其次,;其次, 输入参数还需有输入参数还需有3 3个柱子的代号个柱子的代号, ,我们令我们令3 3个柱子的参数名分个柱子的参数名分 别为别为fromPegfromPeg,auxPegauxPeg和和toPegtoPeg;最后,汉诺塔问题的求解;最后,汉
11、诺塔问题的求解 是一个处理过程,因此算法的输出是是一个处理过程,因此算法的输出是n n个盘子从柱子个盘子从柱子 fromPegfromPeg借助柱子借助柱子auxPegauxPeg移动到柱子移动到柱子toPegtoPeg的移动步骤,我的移动步骤,我 们设计每一步的移动为屏幕显示如下形式的信息:们设计每一步的移动为屏幕显示如下形式的信息: Move Disk i from Peg X to Peg YMove Disk i from Peg X to Peg Y 这样,汉诺塔问题的递归算法可设计如下:这样,汉诺塔问题的递归算法可设计如下: 数据结构C语言版-第06章21 void towers(
12、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移至移至auxPeg towers(n-1,fromPeg,auxPeg,toPeg); /把圆盘把圆盘n由由fromPeg直接移至直接移至toPeg printf(%s%d%s%c%s%cn, move disk , n, from peg , fromPeg,
13、 to peg , toPeg); /把把n-1个圆盘从个圆盘从auxPeg借助借助fromPeg移至移至toPeg towers(n-1,auxPeg,toPeg,fromPeg); 数据结构C语言版-第06章22 测试主函数如下:测试主函数如下: #include void main(void) Towers(4, A, C, B); 程序运行的输出信息如下:程序运行的输出信息如下: 数据结构C语言版-第06章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 t
14、o Peg C Move Disk 3 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
15、 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 数据结构C语言版-第06章24 总结如下:递归算法的执行过程是不断地自调用,直总结如下:递归算法的执行过程是不断地自调用,直 到到达递归出口才结束自调用过程;到达递归出口后,递到到达递归出口才结束自调用过程;到达递归出口后,递 归算法开始按最后调用的过程最先返回的次序返回;返回归算法开始按最后调用的过程最先返回的次序返回;返回 到最外层的调用语句时递归算法执行过程结束到最外层的调用语句时递归算法执行过程结束。 数
16、据结构C语言版-第06章25 6.46.4递归过程和运行时栈递归过程和运行时栈 对于非递归函数,调用函数在调用被调用函数前,系对于非递归函数,调用函数在调用被调用函数前,系 统要保存以下两类信息:统要保存以下两类信息: (1 1)调用函数的返回地址;)调用函数的返回地址; (2 2)调用函数的局部变量值。)调用函数的局部变量值。 当执行完被调用函数,返回调用函数前,系统首先要当执行完被调用函数,返回调用函数前,系统首先要 恢复调用函数的局部变量值,然后返回调用函数的返回恢复调用函数的局部变量值,然后返回调用函数的返回 地址。地址。 数据结构C语言版-第06章26 递归函数被调用时,系统要作的工
17、作和非递归函递归函数被调用时,系统要作的工作和非递归函 数被调用时系统要作的工作在形式上类同,但保存信息数被调用时系统要作的工作在形式上类同,但保存信息 的方法不同。的方法不同。 递归函数被调用时,系统需要一个运行时栈递归函数被调用时,系统需要一个运行时栈. .系统的系统的 运行时栈也要保存上述两类信息。每一层递归调用所需运行时栈也要保存上述两类信息。每一层递归调用所需 保存的信息构成运行时栈的一个工作记录,在每进入下保存的信息构成运行时栈的一个工作记录,在每进入下 一层递归调用时,系统就建立一个新的工作记录,并把一层递归调用时,系统就建立一个新的工作记录,并把 这个工作记录进栈成为运行时栈新
18、的栈顶;每返回一层这个工作记录进栈成为运行时栈新的栈顶;每返回一层 递归调用,就退栈一个工作记录。因为栈顶的工作记录递归调用,就退栈一个工作记录。因为栈顶的工作记录 必定是当前正在运行的递归函数的工作记录,所以栈顶必定是当前正在运行的递归函数的工作记录,所以栈顶 的工作记录也称为活动记录。的工作记录也称为活动记录。 数据结构C语言版-第06章27 6.56.5递归算法的效率分析递归算法的效率分析 斐波那契数列斐波那契数列Fib(n)Fib(n)的递推定义是:的递推定义是: 求第求第n n项斐波那契数列的递归函数如下:项斐波那契数列的递归函数如下: long Fib(int n) if(n =
19、0 | n = 1) return n; /递归出口递归出口 else return Fib(n-1) + Fib(n-2); /递归调用递归调用 数据结构C语言版-第06章28 用归纳法可以证明求用归纳法可以证明求Fib(n)的递归调用次数等于的递归调用次数等于2n-1;计算斐波;计算斐波 那契数列的递归函数那契数列的递归函数Fib(n)的时间复杂度为的时间复杂度为O(2n)。计算斐波那契数。计算斐波那契数 列列Fib(n)问题,我们也可根据公式写出循环方式求解的函数如下:问题,我们也可根据公式写出循环方式求解的函数如下: 图图6-6 Fib(5)6-6 Fib(5)的递归调用树的递归调用树
20、 数据结构C语言版-第06章29 long Fib2(int n) long int oneBack, twoBack, current; int i; if(n = 0 | n = 1) return n; else oneBack = 1; twoBack = 0; for(i = 2; i = n; i+) current = oneBack + twoBack; twoBack = oneBack; oneBack = current; return current; 数据结构C语言版-第06章30 上述循环方式的计算斐波那契数列的函数上述循环方式的计算斐波那契数列的函数Fib2(n)
21、的时的时 间复杂度为间复杂度为O(n)。对比循环结构的。对比循环结构的Fib2(n)和递归结构的和递归结构的 Fib(n)可发现,循环结构的可发现,循环结构的Fib2(n)算法在计算第算法在计算第n项的斐项的斐 波那契数列时保存了当前已经计算得到的第波那契数列时保存了当前已经计算得到的第n-1项和第项和第n-2 项的斐波那契数列,因此其时间复杂度为项的斐波那契数列,因此其时间复杂度为O(n);而递归;而递归 结构的结构的Fib(n)算法在计算第算法在计算第n项的斐波那契数列时,必须项的斐波那契数列时,必须 首先计算第首先计算第n-1项和第项和第n-2项的斐波那契数列,而某次递归项的斐波那契数列
22、,而某次递归 计算得出的斐波那契数列,如计算得出的斐波那契数列,如Fib(n-1)、Fib(n-2)等无法等无法 保存,下一次要用到时还需要重新递归计算,因此其时保存,下一次要用到时还需要重新递归计算,因此其时 间复杂度为间复杂度为O(2n) 。 数据结构C语言版-第06章31 * *6.66.6递归算法到非递归算法的转换递归算法到非递归算法的转换 有些问题需要用低级程序设计语言来实现,而低级有些问题需要用低级程序设计语言来实现,而低级 程序设计语言(如汇编语言)一般不支持递归,此时程序设计语言(如汇编语言)一般不支持递归,此时 需要采用问题的非递归结构算法。一般来说,存在如需要采用问题的非递
23、归结构算法。一般来说,存在如 下两种情况的递归算法。下两种情况的递归算法。 (1 1)存在不借助堆栈的循环结构的非递归算法,如)存在不借助堆栈的循环结构的非递归算法,如 阶乘计算问题、斐波那契数列的计算问题、折半查找阶乘计算问题、斐波那契数列的计算问题、折半查找 问题等。这种情况,可以直接选用循环结构的算法。问题等。这种情况,可以直接选用循环结构的算法。 数据结构C语言版-第06章32 (2 2)存在借助堆栈的循环结构的非递归算法,所有递归算法)存在借助堆栈的循环结构的非递归算法,所有递归算法 都可以借助堆栈转换成循环结构的非递归算法,如下边例都可以借助堆栈转换成循环结构的非递归算法,如下边例
24、6-46-4 设计的汉诺塔问题的借助堆栈的循环结构的非递归算法。此时设计的汉诺塔问题的借助堆栈的循环结构的非递归算法。此时 可以把递归算法转换成相应的非递归算法,有两种转换方法:可以把递归算法转换成相应的非递归算法,有两种转换方法: 一种方法是借助堆栈,用非递归算法形式化模拟递归算法的执一种方法是借助堆栈,用非递归算法形式化模拟递归算法的执 行过程;另一种方法是根据要求解问题的特点,设计借助堆栈行过程;另一种方法是根据要求解问题的特点,设计借助堆栈 的循环结构算法。这两种方法都需要使用堆栈,这是因为堆栈的循环结构算法。这两种方法都需要使用堆栈,这是因为堆栈 的后进先出特点正好和递归函数的运行特
25、点相吻合。下面讨论的后进先出特点正好和递归函数的运行特点相吻合。下面讨论 的例的例6-46-4是第二种情况下的第一种转换方法的例子是第二种情况下的第一种转换方法的例子 数据结构C语言版-第06章33 6.76.7设计举例设计举例 6.7.1 6.7.1 一般递归算法设计举例一般递归算法设计举例 例例6-5 6-5 设计一个输出如下形式数值的递归设计一个输出如下形式数值的递归 算法。算法。 n n n . nn n n . n . . 3 3 3 3 3 3 2 22 2 1 1 数据结构C语言版-第06章34 问题分析:该问题可以看成由两部分组成:一部分是输出一问题分析:该问题可以看成由两部分
26、组成:一部分是输出一 行值为行值为n的数值;另一部分是原问题的子问题,其参数为的数值;另一部分是原问题的子问题,其参数为n-1。 当参数减到当参数减到0时不再输出任何数据值,因此递归的出口是当参时不再输出任何数据值,因此递归的出口是当参 数数n0时空语句返回。时空语句返回。 算法设计:递归算法设计如下:算法设计:递归算法设计如下: void Display(int n) int i; for(i = 1; i = n; i+) coutsetw(s)n; cout 0) Display(n - 1);/递归递归 /n=0为递归出口,递归出口为空语句为递归出口,递归出口为空语句 数据结构C语言版
27、-第06章35 例例6-6 设计求解委员会问题的算法。委员会问题是:设计求解委员会问题的算法。委员会问题是: 从一个有从一个有n个人的团体中抽出个人的团体中抽出k (kn)个人组成一个委个人组成一个委 员会,计算共有多少种构成方法。员会,计算共有多少种构成方法。 问题分析:从问题分析:从n个人中抽出个人中抽出k(kn)个人的问题是一个个人的问题是一个 组合问题。把组合问题。把n个人固定位置后,从个人固定位置后,从n个人中抽出个人中抽出k个个 人的问题可分解为两部分之和:第一部分是第一个人人的问题可分解为两部分之和:第一部分是第一个人 包括在包括在k个人中,第二部分是第一个人不包括在个人中,第二部分是第一个人不包括在k个人个人 中。对于第一部分,则问题简化为从中。对于第一部分,则问题简化为从n-1个人中抽出个人中抽出k- 1个人的问题;对于第二部分,则问题简化为从个人的问题;对于第二部分,则问题简化为从n-1个个 人中抽出人中抽出k个人的问题。图个人的问题。图6-7给出了给出了n=5, k=2时问题时问题 的分解示意图。的分解示意图。 数据结构C语言版-第06章36 图图6-7 6-7 委员会问题分解示意图委员会问题分解示意图 数据结构C语言版-第06章37 当当n=k或或k=0时,该问题可直接求解,数值均为时,该问题可直接求解,数值
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 赣州启明星眼科医院工作制度及职责汇编
- 电子支付平台安全支付技术升级与应用推广方案
- 车辆安全责任书14篇
- 熟人医患关系事迹分享
- 《喜看稻菽千重浪 记首届国家最高科技奖获得者袁隆平》袁隆平的农业科技成果的转化风险课件
- 特岗考试文综试题及答案
- 药品采购管理制度试题及答案
- 药品经营企业法律法规及 GSP 规范岗前培训试题及答案
- 药品生产质量管理规范试题及答案
- 铁路供电运维试题及答案
- 油田助剂车间管理办法
- 小学一年级下册生字笔顺组词造句阅读本
- 矿业项目进退场交接措施
- JG/T 3028-1995住宅厨房排烟道
- 小学语文六年级下册第一单元大单元作业设计
- T/CHES 59-2021组合式金属防洪挡板安装、验收及维护规范
- 宁夏砖瓦用粘土矿产地质勘查技术规程 DB64-T 1754-2020
- 青光眼的观察与护理
- 《跨境电子商务法律法规 》全套教学课件
- 电工实训项目二常用电工工具、仪表使用模块二 认识和使用常用电工仪表
- 残疾人证管理实施细则
评论
0/150
提交评论