数据结构与程序设计-递归
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第5章递归
5.1 递归简介
(Introduction to Recursion)
5.2 递归的原理
(Principles of Recursion)
5.3 回溯: 将工作延迟
(Backtracking: Postponing the Work)
5.4 树形结构编程: 在游戏中提前考虑走法
(Tree-Structured Programs: Look-Ahead in Games)
n掌握:
1.递归的概念:什么是递归、种类、及递归求解
方法。
2.递归过程的机制与利用递归工作栈实现递归的
方法。
3.利用递归解决问题的分治法和回溯法。
n了解:
n迷宫问题和n皇后问题的递归思路及利用栈实现的非递归解法。
n目的:
n通过实例分析递归执行的过程和实现的方式,从而使读者掌握递归适用的场合。
5.1 递归简介
递归与递归程序的概念
n递归(recursion)是一种描述和解决问题的基本方法,用来解决可归纳描述的问题,或说可分解为结构自相似的问题。所谓结构自相似,是指构成问题的部分与问题本身在结构上相似。
n递归的定义
n1)定义一个对象,又用到这个对象的本身;
n2)定义一个结构,它的每一个部分又是这种结构;
n3)定义一个过程,在执行中又直接或间接地调用过程
自己;
n递归程序
n在计算机中,递归问题可使用递归程序解决。
5.1 递归简介
n5.1.1 用于函数调用的堆栈
n5.1.2 表示函数调用的树
n5.1.3 用递归计算数的阶乘
n5.1.4 用分治算法解决汉诺塔问题
5.1.1 用于函数调用的堆栈
n调用记录(invocation record)——为每个调用函数分配的临时存储区域,包括返回地址、调用参数、局部变量等
n函数嵌套调用——函数按“后进先出”次序;执行函数所使用的临时存储区域也具有“后进先出”的特性;于是调用记录必须用“堆栈”保存
n堆栈的变化状态(stack frame)P.158图5.1
图5.1 stack frames for function calls
n递归调用的stack frame与一般的函数调用类似。
5.1.2 表示函数调用的树
n可以用“树”表示函数调用的次序(根节点代表主程序;其它节点代表所调用的某个函数)
n与树有关的术语(孩子、双亲、分支、兄弟、叶子/外部节点、路径、树/节点的高度/层数、树的遍历)
n递归树:P.159图5.2
n用于存储“调用记录”的堆栈(stack frame)的
空间需求——与递归树的高度成正比——于是可以利用递归树分析递归算法的性能。
图5.2 递归树
5.1.4 递归应用:用分治法解决汉诺塔问题分治法
n对于一个较为复杂的问题,如果能够分解成几个相对简单的且解法相同或类似的子问题来求解,这种方法叫分治法。
n Tower of Hanoi问题是一个典型的适合用递归的方法来解决的问题。
n问题描述:如图5.3所示,有A,B,C三个塔座,A上套有n个直径不同的圆盘,按直径从小到大叠放,形如宝塔,编号1,2,3……n。要求将n个圆盘从A移到C,叠放顺序不变,移动过程中遵循下列原则:n每次只能移一个圆盘
n圆盘可在三个塔座上任意移动
n任何时刻,每个塔座上不能将大盘压到小盘上
图5.3 Hanoi塔
解决方法:
n 1. n=1时,直接把圆盘从A移到C
n 2. n>1时,将n个圆盘从A塔座上移到C塔座上可以分为以下三个步骤进行:
⑴将A塔座上的n-1个圆盘借助C塔座先移到B塔座上。
⑵把A塔座上剩下的一个圆盘移到C塔座上。
⑶将n-1个圆盘从B塔座借助A塔座移到C塔座上。
n这样就将求解n个圆盘的Hanoi问题转化为求解n-个圆盘的Hanoi问题,依次类推,直至转化成只有一个圆盘的Hanoi问题。
实现算法:
//Main program:
const int disks = 64; // Make this constant much smaller to run program.
void move(int count, int start, int finish, int temp);
/* Pre: None.
Post: The simulation of the Towers of Hanoi has terminated. */
main( )
{
move(disks, 1, 3, 2);
}
//Recursive function:
void move(int count, int start, int finish, int temp)
{
if (count > 0)
{
move(count-1, start, temp, finish);
cout<<"Move disk "< <<" to "< move(count-1, temp, finish, start); } } 求解汉诺塔问题的递归树(n=3) n小结: n递归算法的效率往往很低, 费时和费内存空间. 但是递归也有其长处, 它能使一个蕴含递归关系且结构复杂的程序简介精炼, 增加可读性. 特别是在难于找到从边界到解的全过程的情况下, 如果把问题推进一步没其结果仍维持原问题的关系, 则采用递归算法编程比较合适.