递归程序设计
递归算法在程序设计中的应用分析
递 归严 格 说 来 并 不 是 一 种 具 体 的 算 法
递归的本 质在于在 调用的过 程 中, 问
量 都 可 以 作 为 参数 , 参数 的 选 择 具 备 一 定
实 例 : 于 一个 整 数 1的划 分 , 是 把 1 对 " 1 就 " 1
策略 , 指 函数 / 程 / 是 过 子程 序 在 运行 过程 题 的规 模 会 缩 小 , 用 递 归得 到 的 相 应 的 的技 巧 。 使 可 中直 接 或 间 接 调 用 自身 的 行 为 。 归 是 计 子 问题 更 容 易 解 决 , 以 用 递 归 方 程 来 表 递 归思 想 的算 法 被 称 为 递 归算 法 。 归 的 方 度 , 递 问题 就 可 以直 接 解 决 , 为 边 界 条 件 。 称 写程 序 能 使 程 序 变 得 简 洁 和 清 晰 。 是 用 但 递 归方 式 所 描 述 的 算 法 , 生 一 方 面 对 于 学
则 在 程 序 设 计 与 分析 中 , 归 技 术 是 十 以 及 递 归 方 程 , 问 题 很 容 易 解 决 。 递 2 1递归 类型 的分类 .
按 照 所 应 用 类 型 的 不 同 , 归 算 法 可 里 如 果 确 定 了 一 个 数 , 问题 的 规 模 自然 递 则
缩 小 。 时考 虑 添 加 参 数 I , 示 参 与 划 分 这 n表 的 最 大 数 , ( , ) 我 们惊 奇 的 发现 , 要 qn i 。 n 只 ( ) 于 归纳 的 递 归算 法 。 1基
执 行 的 步 骤 及过 程 , 一 方 面 需 要 自己 编 另 写程序时更是没有头绪 。
2 递归的计 算思维方式
递 归 算 法 设 计 的 关 键 在 于 如 何 设 定 代
常见的程序设计方法
常见的程序设计方法在计算机程序设计中,常见的程序设计方法有许多种。
程序设计是将问题转化为计算机可以理解和执行的指令或代码的过程,而不同的问题和需求通常需要使用不同的程序设计方法来解决。
下面将介绍一些常见的程序设计方法。
1. 顺序程序设计顺序程序设计是最基础的程序设计方法之一。
顺序程序设计按照指令的顺序逐步执行,从上到下,从左到右。
开发者需要按照问题的逻辑和需求,将指令按照正确的顺序编写。
这种方法简单明了,适用于一些简单的问题,但对于复杂的问题可能会显得不够灵活。
2. 分支程序设计分支程序设计基于条件语句,根据不同的条件选择不同的执行路径。
常见的条件语句有if语句和switch语句。
开发者可以根据不同的条件,执行不同的代码块,从而实现问题的不同分支。
分支程序设计适用于需要根据条件进行不同操作的问题,可以增加程序的灵活性和适应性。
3. 循环程序设计循环程序设计允许程序根据需要重复执行一段代码块。
循环语句的常见形式有for循环、while循环和do-while循环。
循环程序设计可以逐次迭代一个过程,直到满足退出条件为止。
这种方法适用于需要重复执行相同或类似操作的问题,提高了程序的效率和可重用性。
4. 递归程序设计递归程序设计是指一个函数或过程在执行过程中调用自身的方法。
通过递归,一个复杂的问题可以被拆分为多个相同或类似的子问题,从而简化解决步骤。
递归程序设计适用于问题可以自我分解为更小规模问题的情况,但需要注意递归深度和终止条件以避免无限循环。
5. 面向对象程序设计面向对象程序设计是一种以对象和类为基本单位的程序设计方法。
它将数据和操作这些数据的函数封装成对象,通过对象之间的交互来解决问题。
面向对象程序设计具有抽象、封装、继承和多态等特性,可以更好地模拟和解决现实世界中的问题。
面向对象程序设计适用于复杂的问题,提高了代码的可读性和可维护性。
6. 函数式程序设计函数式程序设计是一种基于数学函数概念的程序设计方法。
如何用递归方法进行程序设计
= { 3 { { 【】) ) 4 ( { 1 } } 5 4 { 2 l aO , > 5 { 3 2 { 1 ’ )
这 种从 目 的项 a5出发 , 据 表 达式 ( ) 为 不断 f1 根 1变
绪 。因此 。 文 试 图帮 助初 学 者解 决 以下几 个 问题 : 本 什 求 前 一 项 , 到 一个 已 知 的项 , 通 过 不 断 回代 计算 . 直 再 直 称 么是递 归 方法 ? 何递 归方 法 可 以得 到正 确 的解 ? 证 得 到后 续 项 , 到解 出 目的项 的计 算 过 程 , 为 递归 方 为 保 递 归 方法 求解 正 确 的条 件 是什 么 ?如 何 应 用递 归方 法 法 。 进 行 问题 求解 及 如何 设计 递 归 程序 ? 第二种 方法 即递归方法 能正确求解 .是 由于不断 1递归 方 法 的概 念 以及 保 证 递 归方 法 求 解 正确 性 的条 进 行 问题 转 化直 到一 个 已知项 , . 然后 回代 。 回代 过程 在 件 中 以递推 方法 进 行 。 因此 , 只要 第 一步 的 问题转 化 过程 与递 归 方 法非 常 相 近 的是 递 推 方 法 。为 了弄 清 两 正确 .那 么递 归 方法 的正 确 性无 疑 等 价 于递推 方 法 的 正确性。 事实 上 , 在这 个 例 子 中可 以通 过 比较() 3来 2和() 者 的关 系 . 我们 先 看 例题 l 。 例 1对 于数 列 知道 () 1 总 结例 1 我 们有 如下 概 念 : , an n an 1 [] 【一 】 = 当 n O时 , aD= , = 有 【] 1n为 自然 数 , 请求 出 a5。 [] 递 推 方法 : 就是 构 造 低 阶 规 模( 规模 为 i一般 i 如 , _ 分析 : 求 出 a5, 以 用如 下两 种 方法 : 要 [】可 o 的 问题 , 求 出其 解 , 后 推 导 出 问题 规 模 为 il的 】 并 然 + 第 一 种 方法 : 据公 式 an= 掌 [— 】按 照 从 前 向 问题 以及 其解 . 次推 到 规模 为 n的 问题 的解 。 而言 根 [】n an j, 依 简 后 的顺 序 依 次 求 出 a1= * [l l 【】 2 a1= ,【】 之 . 是 从 已知 的 当前 项 出发 , 据表 达 式 向后 推 出下 [l l ao= , 2= ¥ 【】 2a3= a 就 根 直 3a ] =,[ =*[=4a ] *[=2 。 【= 26a ] a 1 ,[ = a ]1 将计算 23 44 32 55 4 0 项 。 到求 出 目的项 的方 法 。 过 程 写在 一起 有 : 递 归方 法 : 就是 将 规 模 为 1的 问题 , 阶成 若 干个 1 降
程序设计课程中的递归算法分析
7 6
安 阳 师 范 学 院 学 报
20 02薤
t ( )/*调 用 试 探 放 置 的 函 数 , 第 1 皇 后 选 r 1; v 为 个
位 要 在 第 2列 上 放 皇 后 。 , 被 , 由 循 环 中找到 j =3时 位 置合 适 , 后第 三次 然
/*n m存 放解 的个 数 * u /
vi p n( , ) o r t) t ; d i ( f (1 , o 1 =l m( =1 ; r" 1 6 m+ +)
{[ 一l a m] ; bm [ =1 ;
c m] ; [ =l
维普资讯
[ 收稿 日期 ]O l 4 2O 一0 一叭 ( 作者 简介 】 陈佳(94 ) 女 , 阳职业技术学院讲 师。 I6一 , 濮
i 7 ,[ 7 ,[ 7 ,[ ] n a[ ] b 1 ] c 1 ]X 9 ; t m n m=0 _ u 1 ;
m i( a ) n
;t i m; n
[5 表示 左下 一右 上 方 向 的 l 1] 5条斜 线上 有无 皇 后 . 、 、 三 个数 组 都定 义 的足够 大 。x 1 _x 8 ab c [ ]- [ ] -
表示 每列上 放 置 皇后 的行 位 置 。 ij 示 当 前正 、表
在 试探 的第 i 皇后 的列 和行位 置 。 个
[ 关键词】 递归; 子程序 ; 点地 址 ; 斯 堆栈 ; 口参数 ; 人 压栈 [ 田分类号 】 4 中 62 ,
在 子 程序 中直接 或 间接 调 用 自身 叫做 递 归 。 它其 实 是 子程 序嵌 套 调 用 的特 殊 形式 , 只不 过 是 嵌 套 调用 了 自身 。这个概 念 理解 上的 困难 来 自两 方 面 , 要 弄 清楚 这 两点 , 归 也 并 非 是 难 以理 只 递
递归算法在C语言程序设计中的实现
(pc—r h r c o e pt i dUn e i r ut r td , ei 00 6C ia Sae fg t a hI fh il t i rt f r e u y B in 10 7 ,hn) i B n t Ca aUn e v sy o F h S jg
维普资讯
.
开 发研 究 与设 计 技术 . . . 。。.
本 目 任 辑: 嫒 栏责编 谢媛
递归算法在 C语言程序设计中的实现
叶 静
( 首都联合职工 大学航 天一分校 , 北京 107 ) 0 0 6
摘要 : 本文根据递 归算法 的定 艾, 对其在 c语 言程序设计 中的应用进行 了阐述. 通过 对递 归的 内部 实现过程的描述, 对递归的使 用进 行评 价 , 明递 归在 程 序设 计 中 具有 一 定 的使 用 空 间. 说 关■词 : 归: 递 程序 设 计
用 递 归算 法 。其 实 只要 写 出递 归公 式 和考 虑 参 数是 l的情 况 时怎 样处理就可 以了。使用递归公式这种情况一般需要 函数带 回一个
2什 么是 递归
在数学中递归 的定义 : 若一个对象部分地包含它 自己. 它 或用 自己给 自己定义, 则称这个对象是递归的。 用递归来描述的算法称 为递 归算 法 。 递归 算 法 存 在 的 两 个必 要 条 件 : () 1过程 的描述中包含它 自身 : ( ) 明确 的结束递 归的条件 ; Z有 , 在 C语言 中递归算法的应用就是使用递 归函数 . 所谓 递归函 数就是 自调 用函数 , 在函数体内直接或 问接 的调用 自己。因此递
归函数必须 满足以上二个必要条件 . 其特点是 : 首先 , 在每一次 调 用 自己时 , 使用相 同的解 决问题 的方 法 , 调用 函数的参数每 次 但 不同( 有规 律的变化 )其次 , 须有一个终止处 理( ; 必 结束递 归 ) 的 条件 , 如一个测试 , 当满足这个条件时 , 可得 到直接解并能够终 止
C++算法-4.递归算法
if (x==a[mid]) cout<<"YES"<<endl; else if (x<a[mid]) search(x,mid+1,bot); else search(x,top,mid-1); } else cout<<"NO"<<endl; }
//找到就输出 //判断在前半段还是后半段查找
【例2】 设有N个数已经按从大到小的顺序排列,现在输入X,判断它是 否在这N个数中,如果存在则输出:“YES” 否则输出“NO”。 【算法分析】 该问题属于数据的查找问题,数据查找有多种方法,通常方法是:顺 序查找和二分查找,当N个数排好序时,用二分查找方法速度大大加快。 二分查找算法: (1) 设有N个数,存放在A数组中,待查找数为X,用L指向数据的高 端,用R指向数据的低端,MID指向中间: (2) 若X=A[MID] 输出 “YES”; (3)若X<A[MID]则到数据后半段查找:R不变,L=MID+1,计算新的 MID值,并进行新的一段查找; (4) 若X>A[MID]则到数据前半段查找:L不变,R=MID-1,计算新的 MID值,并进行新的一段查找; (5)若L>R都没有查找到,则输出“NO”。 该算法符合递归程序设计的基本规律,可以用递归方法设计。
程序设计教学中递归调用问题研讨
二 、 归 条 件 及 规 则 递
1 递 归 条 件 .
、
递 归 的概 念 以 及 内部 实现 机 制
1 递 归 的 基 本 概 念 … .
采 用 递 归 方 法 来 解 决 问 题 时 , 须 符 合 以下 三 个 条 件 : 必
( ) 许 把 要 解 决 的 问题 转 化 为 一 个 新 问题 , 这 个 新 问 1允 且
所 谓 递 归 调 用 是 指 在 函 数 内 部 直 接 或 间 接 调 用 其 自身 , 把 复 杂 问题 转 化 为 简 单 问 题 的 方 法 。递 归 程 序 从 本 质 上 说 是
一
在 执 行 返 回 操 作 时 , 序 内部 要 实 现 以 下 操 作 :1 若 函 数 程 () 需 要 求 值 , 需 将 其 值 保 存 到 回传 变 量 中 ;2 从 栈 顶 取 出返 回 则 () 地 址 , 栈 ( 时 撤 销 被 调 用 层 子 程 序 的 局 部 变 量 和 形 参 ) 退 同 ; () 据 返 回地 址 返 回 ;4 在 返 回 后 , 函数 需 要 求 值 , 从 回 3依 () 若 则 传 变 量 中取 出 所 保 存 的 值 并 传 送 给 相应 的 实 参 或 位 置 。
【 学教改研究 】 教
程 序 设 计 教 学 中 递 归 调 用 问 题 研 讨
王 志辉
( 山西 青 年 管 理 干 部 学 院 , 西 太 原 0 0 0 ) 山 3程 序 设 计 教 学过 程 中的 一 个 重点 与难 点 内容 。 为 了解 决在 学 习递 归过 程 中存 在 的 问题 , 到 良 递 达
种 循 环 结 构 , 把 相 对 复 杂 的 计 算 逐 次 归 结 为 相 对 简 单 的 计 它
程序设计中的递归算法分析
晰 。 本 文 针 对 学生 在 学 习程序 设 计课 程 时 对递 归 算 法 难 以 理 解 及 掌握 等 情 况 , 阐述 了递 归算 法 的 本 质 及 解 决 问题 的 思路 。
【 关键 词 】 递 归 栈 算 法 :
O 引言 、
递归 算 法 设 计 . 常 有 以下 3个 步骤 : 通
递 归 部 分 } /
在 定 义 一个 过 程 或 函 数 时 出现 了调 用 本 过 程 或 者 函数 的成
分 .g 调 用 自己 本 身 , 称 之 为 直 接 递 归 , 过 程 函数 P调 用 过 口 这 若
} 下面 应 当 设 置边 界 条 件 , 则 程 序 就 将 无 限递 归下 去 。 以 否 可 函数 改 为 : fc ( t ) ati nN
应 的 程 序 显 得较 为 重 要 。 但是 . 递 归 方 式 所 描 述 的 算 法 , 用 在一 般 计 算 机 语 言 教材 中 占有 较 小 的篇 幅 . 生 不 容 易 理 解 . 不 明 学 弄 白递 归 函数 执行 的步 骤 及 过程 .尤 其 需 要 自 已编 写 程 序 时 更 觉
增 加 或 减 少 . 归 调 用 的 次数 必 须 是 有 限 的 . 须 有 递 归 结 束 的 的 圆 盘 , 号 为 12 … … n 1 n 现 在 要 把 A 上 的 B个 盘 移 到 递 必 编 、、 一 、。
归结为” 简单… 较 情形 的 计 算 . 得 到 计 算 结 果 为 止 。 对 于 问题 并 定 义 是 递 归 的 .数 据 结 构 是 递 归 的 .问 题 解 法 是 递 归 的 ,都 可
以 采 用递 归 方 法 来 处理
{ r unN fc e r at 一 l t 1
C语言与程序设计ppt-第12章递归
第12章 递 归
华中科技大学计算机学院 卢萍
华中科技大学计算机学院C语言课
2021/4/25
程组
1
本章讲授内容
递归(recursion)是一项非常重要的编 程技巧,可以使程序变得简洁和清晰,是 许多复杂算法的基础。本章介绍 递归、递归函数的概念; 递归的执行过程; 典型问题的递归函数设计; 分治法与快速排序; 回溯法; 递归在动态规划等算法中的应用。
12
【例12.3】 设计一个求解汉诺塔问题的算法。
这是一个典型的用递归方法求解的问题。要移动n个 盘子,可先考虑如何移动n 1个盘子。分解为以下3 个步骤:
(1)把A上的n-1个盘子借助C移到B。 (2)把A上剩下的盘子(即最大的那个)移到C。 (3)把B上的n-1个盘子借助A移到C。 其中,第(1)步和第(3)步又可用同样的3步继
2021/4/25
华中科技大学计算机学院C语言课程组
2
12.1 递归概述
递归是一种函数在其定义中直接或间接调用 自己的编程技巧。递归策略只需少量代码就 可描述出解题过程所需要的多次重复计算, 十分简单且易于理解。
递归调用:函数直接调用自己或通过另一函 数间接调用自己的函数调用方式
递归函数:在函数定义中含有递归调用的函 数
续分解,依次分解下去,盘子数目n每次减少1,直 至n为1结束。这显然是一个递归过程,递归结束条 件是n为1。
2021/4/25
华中科技大学计算机学院C语言课程组
13
函数move(n,a,b,c)
为了更清楚地描述算法,可以定义一个函数 move(n,a,b,c)。该函数的功能是:将n个盘 子从木桩a上借助木桩b移动到木桩c上。算法 的第(1)步和第(3)步的实现都是递归调 用,分别为move(n-1,a,c,b)和move(n1,b,a,c)。
常见的程序设计方法
常见的程序设计方法常见的程序设计方法1. 顺序程序设计顺序程序设计是一种最基础的程序设计方法,它是按照程序中各个语句的先后顺序执行,没有分支和循环的控制结构。
程序从开始执行,按照语句的顺序逐一执行,直到结束。
2. 分支程序设计分支程序设计是在程序执行过程中根据条件的不同选择执行不同的语句或语句块。
常见的分支程序设计包括if语句和switch语句。
if语句根据条件的真假执行不同的代码块,而switch语句根据不同的取值执行相应的代码块。
3. 循环程序设计循环程序设计是在程序执行过程中根据条件的不同重复执行某段代码块。
常见的循环程序设计包括while循环、do-while循环和for循环。
while循环在执行前先判断条件,如果条件为真则执行循环体,执行完循环体后判断条件,直到条件为假才结束循环。
do-while循环先执行一次循环体,然后再判断条件,如果条件为真则继续执行循环体,直到条件为假才结束循环。
for循环是一种常用的循环结构,它在执行前初始化一个计数器,然后在每次循环迭代时执行循环体,并更新计数器,直到满足循环结束的条件。
4. 递归程序设计递归程序设计是指一个函数在函数体内调用自身的过程。
递归函数通常包含一个或多个终止条件,当满足终止条件时,递归停止并返回结果,否则继续调用自身进行下一步计算。
5. 模块化程序设计模块化程序设计是将整个程序划分为多个模块或函数的过程。
每个模块或函数负责完成特定的任务,通过调用其他模块或函数实现功能的组合。
模块化程序设计使得程序结构清晰,易于维护和调试,并且可以提高代码的重用性。
6. 面向对象程序设计面向对象程序设计是一种基于对象的程序设计方法。
面向对象程序设计的核心概念是类和对象,通过定义类来描述对象的属性和行为,并通过创建对象来实现功能。
面向对象程序设计具有封装性、继承性和多态性等特点,使得程序的设计和开发更加灵活和可扩展。
,常见的程序设计方法包括顺序程序设计、分支程序设计、循环程序设计、递归程序设计、模块化程序设计和面向对象程序设计。
c++中递归的理解
c++中递归的理解
答:在C++中,递归是一种程序设计方法,它是指函数直接或间接调用自身的方法。
这种方法在解决某些问题时非常有效,比如树的遍历、图的搜索等。
递归函数的基本思想是将一个大问题分解成小规模的相同问题。
递归函数在解决实际问题时,需要满足两个条件:
1. 基准情况(Base Case):确定问题的规模缩小到一定程度时,可以直接求解的情况。
2. 递归情况(Recursive Case):把原问题分解成两个或更多个相同但规模较小的问题,并继续递归求解的情况。
使用递归时需要注意以下几点:
1. 递归需要有终止条件,否则会无限递归下去,导致栈溢出等问题。
2. 递归的效率不一定比非递归的方法高,因为多次调用函数会导致额外的函数调用开销和参数传递开销。
3. 递归的算法通常比较难以理解和调试,因为需要理解函数的调用层次和递归过程。
程序设计中递归的探讨
fc 5 的递 归 调 用 过 程示 意 网如 图 l所 示 。 a()
针 对这 种 情 况 , 们 分别 加 以举 例 进 行 分 析 。 我
/
一
/
归算 法 , 此 , 了 活 跃 思 维 , 因 为 提供 多 样 化 的解 题 方 案 ,
典 型 的有 H n i 题 等 。但 因 为 该 例 子 已 经 被 阐 述 的 ao 问
本文举一个 单链表 的例子 。图 2 示单链表 为有序链 所
表 . 将 一 值 a 入 到链 表 合 适 位 置 。 现 插
递 归方 法 . 实 际上 由 于结 构 的特 殊 性 . 可 以 采 用 递 但 也
根 据 前 文 的叙 述 . 计 成 递 归 算 法 时 . 须 用 i_ 设 必 f. _
es 结 构 , 满 足 条 件 . l e i f 处理 出 口 , 最低 层 n 0 1 即 = 、 的情 况 .l 否 则 时 调 用 函 数 自身 。 因此 。 得 出 递 归 算 法 ee s 可
\
实践 与 经 验
\
————— ————一 — — ~
\ \
算 法 的 问题 有 三 种 情况 : () 1 问题 的 定 义 是递 归 的 。 在 实 际 应 用 中 .许 多 数 学 函数 是 递 归定 义 的 例 如: 乘 函数 、 波 那 契 数 列等 阶 斐 ( ) 据 结构 是 递 归 的 2数
较多 .所 以在这里举 另外一个也非常典 型的例子——
递归程序设计
5 - 20
上述讨论表明: (1) 递归程序可以采用不同的计算规则来进行计算; (2) 采用不同的计算规则来计算递归程序时,对相同的变元,计算过程 可能终止,也可能不终止; (3) 如果对于不同的计算规则,相应的递归程序(对相同的自变元)的 计算过程都终止,则它们所得的结果一定相同; (4) 在(3)的情况下,因为计算过程不同,所以虽然得到的结果相同,但 其效率(计算时间和存储量)却可能差别大。 总之,在递归程序的执行过程中,计算规则的选取是很重要的。本章及 后面的章节中,将统一规定: 采用”最左,最内”的计算规则,即在计算过程中,总是先计算最 内层的F中最左的一个。 例如,在例6中,计算A(1,2)的第一种计算顺序就是按”最左,最 内”的计算规则进行的。但在例7中,按”最左,最内”的计算规则 去计算F(1,2)却是不终止的,故不能认为F(1,2)=0. 虽然”最左,最内”的规则未必是最佳的,但现今具有处理递归调用 功能 的程序设计语言大都采用这种计算规则。
5-7
递推与递归
递归是设计和描述算法的一种有力的工具,它在复 杂算法的描述中经常被采用。能采用递归描述的算 法通常有这样特征,为求解规模为N的问题,设法 将它分解成一些规模较小的问题,然后从这些小问 题的解方便地构造出大问题的解,并且这些规模较 小的问题也能采用同样的分解和综合方法,分解成 规模更小的问题,并从这些更小问题的解构造出规 模稍大问题的解。特别的,当规模N=1时,能直接 得到解。
5 - 15
…递归程序的例子…
例3 Fibonacci函数 φ(x)if x=0 then 0 else if x=1 then 1 elseφ(x-1)+ φ(x-2) 其中,x为非负整数 我们有φ(0)=0 φ(1)=1 φ(2)= φ(1)+ φ(0)=0+1=1 φ(3)= φ(2)+ φ(1)=1+1=2 φ(4)= φ(3)+ φ(2)=2+1=3 φ(5)= φ(4)+ φ(3)=3+2=5 … 例4 计算xy 利用下述公式不难编出相应的递 归程序 F(x,y)= xy: 1 y=0 F(x,y)=1 2 y为偶数 F(x,y)=(x*x)y/2 3 y为奇数 F(x,y)=xy-1*x F(x,y)if y=0 then 1 Else if even(y) then F(x*x,y/2) Else F(x,y-1)*x 其中,x 为正实数;y为非负整数 例如:F(4,3)=F(4,2)*4=F(16,1)*4 =F(16,0)*64=64
基于C语言的递归程序设计分析
viPitu (nn)/ 函数能把r od r N m it n 该 l 按要求输 出 ,
ft; i k n
身拷贝 ,完成某个递归调用后 ,控制返回到先前 的调用环境 。这同循环 算法在思想上也是 异曲同工的 。所以我们也完全 可以编写一个循环结构
为例: O= ) !l(
r ll * n n 1):  ̄ l f c( — 0 ln u } 例2 :求F oac 列 ( i nc b 擞 非波纳契 ) 的第r , 顺 该数列表示 如下 : 按照例 1 的方法 ,写出程序如下 : lnf (n n ogb it ) i { i ( = ll n = f( n = l( = 2) ) ① Itl;  ̄l tI 1 T
一
参 考文 献 [Ⅱ R brSde ik 算 法( 一卷) 民邮 电出版社, 0 1 美]oetegwc. C 第 . 人 2 4 0 [1 K ney .oe. 2【 entHR sn离散数 学及 其应用 . 械工业 出版社,05 美] 机 20
l g m it ) / n o 1J: O) f( J
rt ll ; el X 1 l
1 递 归 的基 本条件 循环结构是结构化程序设计 的三种结构之一 ,主要应用在处理某些 需要重复执行特定语句的情况下 ,通常在使用循环时我们需要 明确三个 重要条件 : 1 )循环的初始条件。可以把要解决的问题转化为—个新问题 ,而这 个新的问题的解决方法仍 与原来 的解决方法相同 ,只是所处理 的问题的 规模有规律地递减。也就是说解决问题的方法相同 ,调用 函数的参数每 次不同 ( 有规律地递减 ),如果没有规律也就不能运用递归方法求解。 2 循环的中止条件 ( ) 或在什么情况下循环运行 )。每 个子问题必须 比原来问题的规模更小 ,即使小一号也行 ,如果能够迅速减小规模更好。 3 程序 有趋 于结束 的趋势 。必 定要有 一个 明确 的结束递 归 的条 ) 件 。当问题的规模达到一定程度时 ( 一般的时候应该是规模足够小 ), 问题的解是 已知 的,在这个地方能结束递归调用 ,不然可能导致系统崩 溃或陷入死循环。 而递归作 为一 种算 法 ,在数学上我们 时这样 定义它的 ,以n 的阶乘
浅析程序设计中的递归算法
内 蒙 古 科 技 与 经 济
I n rM o g l ce c c n lg & Ec n my n e n oi S in eTeh oo y a oo
N o.1 7.t 9 h is e he 21 t s u Se p.2 0 01
具 ,它 在 程 序 设 计 语 言 中 用 来 定 义 句 法 ,在 数 据 结 构 中用来 解 决 表或 树 形 结 构 的搜 索 和 排 序 等 问题 。
般 递 归 函数 设 计 的 格 式 为 :
另 外 , 归 在 计 算 方 法 、 筹 学 模 型 、 为 策 略 和 图 递 运 行 论 的研 究 中 都 得 到 了 广 泛 的应 用 。 1 递 归 的 概 念 若 一 个 对 象 部 分 地 包 含 它 自 己 , 用 它 自 己 给 或 自 己 定 义 ,则 称 这 个 对 象 是 递 归 的 ; 程 序 设 计 中 , 在 若 一 个 过 程 直 接 地 或 间 接 地 调 用 自己 , 称 这 个 过 则 程 是 递 归 的 过 程 。 在 定 义 一 个 过 程 或 函 数 时 出 现 了 调 用 本 过 程 或 函 数 的 成 分 ,即 调 用 自 己 本 身 , 之 称
>
次 数 必 须 是 有 限 的 , 须 有 递 归 结 束 的 条 件 。 归 算 必 递 法 的 执 行 过 程 分 为 两 步 , 一 步 是 从 目标 出发 追 溯 第 到源 头 , 为 回溯 。 二 步是 从源 头逐 步 回代达 到 目 称 第 标 , 为 递 推 。 于 存 在 递 推 , 回 溯 时 , 须 保 留其 称 由 在 必 返 回 的 地 址 与 参 数 , 程 序 能 够 返 回 到 调 用 处 继 续 使 执 行 , 一 步是 系统 通过设 置 栈来 实现 的 , 序设 计 这 程 者 无需对 栈 进行 管理 。 3 递 归 算 法 的 设 计 适 宜 用递 归 算 法 求 解 的 问题 的充 要 条 件 是 : 问 题 具 有 某 种 可 借 用 的 类 同 自身 的 子 问 题 描 述 的 性 质 ; 一 有 限 步 的 子 问 题 有 直 接 的解 存 在 。 某 递 归 算 法 的 设 计 , 常 有 以 下 3个 步 骤 : 通
(6)--递归函数程序设计_试卷
f (int n) { return ((n>0) ? 2*f(n-1)+f(n-2) : -1); } 答案:-17
2.下列代码段将会打印出_____。 int f(int x) { return ((x>0)? x*f(x-1):3); } printf(“%d”,f(f(1))); 答案:18
5.对于以下递归函数 f,调用函数 f(“1a2b3c4d”)的输出结果是_____。 int f(char s[]) { if(s[0]==’\0’) return 0; else return (s[0]>=’0’ && s[0]<=’9’)+f(s+1); } 答案:4
二、程序阅读题 1.下列程序的输出是_____。
答案:3#3#3#3
3.下列程序的输出为_____。 #include <stdio.h> int fun(int x) { int t; if(x<=0) t=x; else t=fun(x-1)+fun(x-2); return t; } int main(void) {
int i; for(i=1;i<=3;i++)
int f (int x) {
if(x<=1) return 1; else return f(x-1)+f(x-2); } int main(void) { printf("%d", f(4)); return 0; } 答案:5
2.下列程序的输出是_____。 #include <stdio.h> int main (void) { int k = 1; int a_function ( int j ); k = a_function ( k ); printf ( "%d" , k ); return 0; } int a_function ( int j ) { if ( j < 3 ) { j++; j = a_function ( j ); } printf ( "%d#" , j ); return ( j ); }
递归算法特点
递归算法特点
递归算法是一种程序设计思想,就是把问题划分为几个规模较小的问题处理,用同一的处理方法分别解决这个子问题,最终把小问题的答案组装起来,就得到原问题的答案,从而达到节约计算量的目的。
递归算法具有如下特点:
(1)实现简单:递归算法不一定需要实现复杂的循环,只要确定调用递归函数的调用条件就可以实现简单的递归程序。
(2)易于理解:递归算法相对于循环算法来说,更容易理解,因为算法的每一步大部分只做相同的事情,而且反复调用自身,对理解性质的程序有着极大的帮助。
(3)算法本身的特性决定的:递归算法能够处理接近无限大的计算任务,因为中间调用的关键状态可以独立处理,是由算法本身的特性决定的。
(4)避免使用复杂的循环结构:递归算法能够减少对复杂的数据结构和复杂的循环结构的使用,从而减少程序维护成本和减轻程序员负担。
(5)重复子问题:在递归算法中,同样的子问题会被多次计算,为了解决这一问题可以使用缓存策略,即记录某些子问题的计算结果,当子问题再次出现时载入缓存中的值而无需重复计算,从而节省计算量。
总之,递归算法是一种非常有用的解决方案,能够减少编程复杂度,降低程序维护成本,易于理解,容易调试,效率又较高,有相当的通用性,可以解决一些复杂的计算问题。
递归与递归式
3. 怎么克服递归的效率问题?—化递归为递推
递归:递归是一种从上至下的“分解求解“的过程,即不断 地把大问题分解为小问题,直到小问题规模足够小,然后 求解并进行递归返回和结果合并。——效率差!
递推:递推是一种从下往上的“合并求解“过程,即从解决 小问题出发,记录小问题的答案,并根据已有的小问题的 答案,把问题往大里扩展,“滚雪球”,直到达到大问题 的规模为止。并通常用迭代(循环)的方式实现,而不是 递归调用,一般认为效率上比递归好。
件,称为递归出口,否则会产生死循环而出错。
递归是一种强有力的设计方法 与数学模型一致 表述简单、清晰、代码量少 可读性强、容易证明正确性
递归的问题:执行时间长、运行效率低,特别是 占用空间多,容易造成系统栈的溢出。
主要原因:递归调用时有大量的现场保护与恢 复操作,在递归调用的过程当中系统为每一层的返 回点、局部量等开辟了栈来存储,递归层次数过多 容易造成栈溢出等。
初始条件:a1=1 用递归公式表示为:an+2=2an+1-an,
初始条件:a1=1,a2=2
这里,没有过于细致地区分递归式与递推式,我们视为 一致。
2. 递归式的求解
求解递归式就是化简递归式,以得到形式简单 的限界函数表示(即O、Ω、Θ的表示)。
三种常用方法: 代换法 递归树法 主方法
对表达式细节的简化
例如: 斐波纳契数列的递推公式为fn=fn-1+fn-2 等差数列递推公式:an=an-1+d 等比数列递推公式:bn=bn-1×q
2) 递归式 Recursion
递归公式:当递推式中只含数列中的项,而无常数项或其它 项时,就叫做递归公式。
所以,递归公式属于递推公式的一个特例。 例如,自然数列
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算过程示例
m 20 n 8 k 2 2
确定计算fib(45)所需要的时间的程序
#include <stdio.h> #include <time.h> long fib (int n) { return n<=1 ? 1 : fib(n-1)+fib(n-2); } int main () { double x; x = clock() / CLOCKS_PER_SEC; fib(45); x = clock() / CLOCKS_PER_SEC - x; printf("Timing fib(45): %f.\n", x); return 0; }
long fact (long n) { return n == 0 ? 1 : n * fact(n-1); } long fact(long n) { if (n <= 1) return 1; return n * fact(n - 1); }
main() { printf(“%d”, fact(3)); }
。
2. Fibonacci序列
计算与时间
定义
Fibonacci(斐波那契)序列的递归定义
F0 = 1, F1 = 1 Fn = Fn - 1 + Fn
- 2
(n > 1)
1, 1, 2, 3, 5, 8, 13, 21, 34, 65, 99, …
用递归程序实现
long fib (int n) { return
阅读材料:NP问题
/NP-Problem.html
A problem is assigned to the NP (nondeterministic polynomial time) class if it is solvable in polynomial time by a nondeterministic Turing machine. A P-problem (whose solution time is bounded by a polynomial) is always also NP. If a problem is known to be NP, and a solution to the problem is somehow known, then demonstrating the correctness of the solution can always be reduced to a single P (polynomial time) verification. If P and NP are not equivalent, then the solution of NPproblems requires (in the worst case) an exhaustive search. Linear programming, long known to be NP and thought not to be P, was shown to be P by L. Khachian in 1979. It is an important unsolved problem to determine if all apparently NP problems are actually P. A problem is said to be NP-hard if an algorithm for solving it can be translated into one for solving any other NP-problem. It is much easier to show that a problem is NP than to show that it is NP-hard. A problem which is both NP and NP-hard is called an NP-complete problem.
Fibonacci数的迭代计算
Fibonacci数的递推计算,易见
1)f1和f2是1 2)知道fn-2和fn-1连续两个Fibonacci数,就可算 出下一个fn
递推计算方式
逐个往后推,可用循环实现
fn-1 fn long fib1 (int n) { long f1 = 1, f2 = 1, f3, i;
fn-2 if (n <= 1) return 1; for (f3 = f2 + f1, i = 2; i < n; ++i) { f1 = f2; f2 = f3; f3 = f1 + f2; 做一次 } 递推 return f3;
递推方案
}
程序分析
for (f3 = f2 + f1, i = 2; i < n; ++i) { f1 = f2; f2 = f3; f3 = f1 + f2; } 循环结束时i等于n,这时c的值是fn。 要得到此结论,可设法证明:每次判断 i 的 值时f3正是 fi。
fib(2)
fib(1) fib(0)
fib(1)
fib(1) fib(1)
问题
存在大量重复计算,参数越大重复计算越多。
有关系吗?
随着参数增大,计算中重复增长迅速,最快的微 机上一分钟大约可以算出fib(45) 参数加1,fib多用近一倍时间(指数增长)。最快的 微机一小时算不出fib(55),算fib(100)要数万年 计算需要时间,复杂计算需要很长时间。这是计 算机的本质特征和弱点。说明它不是万能,有些 事情“不能”做。
为计算过程计时
统计程序或程序片段的计算时间有助于理解 程序性质。许多语言或系统都提供了内部计 时功能。 有关函数在time.h,统计程序时间时程序头 部应写
#include <time.h> clock() / CLOCKS_PER_SEC 得到从程序开始到表达式求值时所经历的秒数。
在程序里计时,通常写表达式
注意:这个例子并不是说明递归比循环的效率低。 完全可以写出计算fib的同样高效的递归定义的函 数
最大公约数
求两个整数的最大公约数(greatest common divisor,GCD),写函数 long gcd(long, long) 解法1
从某个数开始,逐个判断当前数是否能同时整除m和n, 在这个过程中记录下能同时整除m和n的最大整数。 需要用一个辅助变量k记录当前需要判断的数。 用一个循环实现k顺序取值
循环不变关系(循环不变量)是理解循环、写好 循环的关键。
问题
本例中用循环的函数比用递归定义的好吗?
新函数在计算时间上有极大优越性。计算时间由循环次 数确定。循环体执行次数大致为n。fib(100)只需约100 次循环,几乎察觉不到所花费时间。 新函数定义较复杂,有复杂的循环。要理解程序意义, 确认函数对任何参数都算出Fibonacci值,需要借助“循 环不变关系”的概念和细致分析。
long fact(1) { if (1 <= 1) return 1; return 1 * fact(1 - 1); }
递归与计算过程
包含递归的程序产生的计算过程和性质更复杂, 能完成很复杂的工作。
递归调用只有一个调用表达式或语句,但是可能要许多 步才能完成。 实际参数的不同,会实际产生的递归调用次数(步数) 也会有很大的不同。 递归程序理解的理解比较困难
递归的函数定义需要有条件语句去控制递归过程 的最终结束
直接给出结果的时候,递归结束; 把对较复杂情况的计算归结为对更简单情况的计算,需 要进行递归处理。
递归和循环
Байду номын сангаас
基本运算、关系判断、条件表达式,加函数 定义和递归定义构成了一个(理论上)“足 够强的”的程序语言。 循环程序可以改成递归实现 递归程序也可以改成循环实现
1. 阶乘和乘幂
例:定义计算整数阶乘的函数
1×2×…×(n - 1)×n
本例中,乘的次数依赖于n,计算所需的次 数定义时无法确定。 这是一种典型循环情况
计算“次数”依赖某些参数的值。
程序
long fact1(long n) { long fac, i; for (fac = 1, i = 1; i <= n; i++) fac *= i; return fac; }
n < 2 ? 1 : fib(n - 1) + fib(n - 2);
}
问题分析:这个程序好不好? 一方面,很好!程序与数学定义的关系很清晰, 正确性容易确认,定义易读易理解
例fib(5)调用过程
fib(5) fib(4) fib(3) fib(2) fib(1) fib(0) 存在什么问题? fib(2) fib(0) fib(3)
归纳证明
第一次判断时 i 的值是 2,f3 的值2,正是 fi(且 f1 的值是fi-1 ,f2 的值是fi-2 ) 若某次判断时 i 值是 k(小于n),循环体中的语 句使f1变成fk-1 ,f2变成fk ,f3变成fk+1 。 i 值增 1 使我们又有f1为fi-2 ,f2变成fi-1 ,f3变成fi 根据归纳法,每次判断 i 的值时f3正是 fi。
阶乘函数的精确定义
1 n0 n! n (n 1)! n 0
是一种递归定义的形式
要解决规模为n的问题,要先解决规模为n-1的子问题, 依此类推。