数据结构与程序设计-递归

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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递归算法的效率往往很低, 费时和费内存空间. 但是递归也有其长处, 它能使一个蕴含递归关系且结构复杂的程序简介精炼, 增加可读性. 特别是在难于找到从边界到解的全过程的情况下, 如果把问题推进一步没其结果仍维持原问题的关系, 则采用递归算法编程比较合适.

相关文档
最新文档