当前位置:文档之家› 函数与递归-程序结构和递归

函数与递归-程序结构和递归

递归调用详解,分析递归调用的详细过程

递归调用详解,分析递归调用的详细过程 2009年05月23日星期六 22:52 一、栈 在说函数递归的时候,顺便说一下栈的概念。 栈是一个后进先出的压入(push)和弹出(pop)式数据结构。在程序运行时,系统每次向栈中压入一个对象,然后栈指针向下移动一个位置。当系统从栈中弹出一个对象时,最近进栈的对象将被弹出。然后栈指针向上移动一个位置。程序员经常利用栈这种数据结构来处理那些最适合用后进先出逻辑来描述的编程问题。这里讨论的程序中的栈在每个程序中都是存在的,它不需要程序员编写代码去维护,而是由运行是系统自动处理。所谓的系统自动维护,实际上就是编译器所产生的程序代码。尽管在源代码中看不到它们,但程序员应该对此有所了解。 再来看看程序中的栈是如何工作的。当一个函数(调用者)调用另一个函数(被调用者)时,运行时系统将把调用者的所有实参和返回地址压入到栈中,栈指针将移到合适的位置来容纳这些数据。最后进栈的是调用者的返回地址。当被调用者开始执行时,系统把被调用者的自变量压入到栈中,并把栈指针再向下移,以保证有足够的空间存储被调用者声明的所有自变量。当调用者把实参压入栈后,被调用者就在栈中以自变量的形式建立了形参。被调用者内部的其他自变量也是存放在栈中的。由于这些进栈操作,栈指针已经移动所有这些局部变量之下。但是被调用者记录了它刚开始执行时的初始栈指针,以他为参考,用正或负的偏移值来访问栈中的变量。当被调用者准备返回时,系统弹出栈中所有的自变量,这时栈指针移动了被调用者刚开始执行时的位置。接着被调用者返回,系统从栈中弹出返回地址,调用者就可以继续执行了。当调用者继续执行时,系统还将从栈中弹出调用者的实参,于是栈指针回到了调用发生前的位置。 可能刚开始学的人看不太懂上面的讲解,栈涉及到指针问题,具体可以看看一些数据结构的书。要想学好编程语言,数据结构是一定要学的。 二、递归 递归,是函数实现的一个很重要的环节,很多程序中都或多或少的使用了递归函数。递归的意思就是函数自己调用自己本身,或者在自己函数调用的下级

《递归算法与递归程序》教学设计

递归算法与递归程序 岳西中学:崔世义一、教学目标 1知识与技能 (1) ?认识递归现象。 (2) ?使用递归算法解决冋题往往能使算法的描述乘法而易于表达 (3) ?理解递归三要素:每次递归调用都要缩小规模;前次递归调用为后次作准备:递归调用必须有条件进行。 (4) ?认识递归算法往往不是咼效的算法。 (5) ? 了解递归现象的规律。 (6) ?能够设计递归程序解决适用于递归解决的问题。 (7) ?能够根据算法写出递归程序。 (8) ? 了解生活中的递归现象,领悟递归现象的既有重复,又有变化的特点,并且从中学习解决问题的一种方法。 2、方法与过程 本节让同学们玩汉诺塔的游戏,导入递归问题,从用普通程序解决斐波那契的兔子问题入手,引导学生用自定义了一个以递归方式解决的函数过程解决问题,同时让同学们做三个递归练习,巩固提高。然后让学生做练习(2) 和练习(3)这两道题目的形式相差很远,但方法和答案却是完全相同的练习,体会其中的奥妙,加深对递归算法的了解。最后用子过程解决汉诺塔的经典问题。 3、情感态度和价值观 结合高中生想象具有较强的随意性、更富于现实性的身心发展特点,综合反映出递归算法的特点,以及递归算法解答某些实践问题通常得很简洁,从而激发学生对程序设计的追求和向往。 二、重点难点 1、教学重点 (1) 了解递归现象和递归算法的特点。 (2) 能够根据问题设计出恰当的递归程序。 2、教学难点 (1) 递归过程思路的建立。 (2) 判断冋题是否适于递归解法。 (3) 正确写出递归程序。 三、教学环境 1、教材处理 教材选自《浙江省普通高中信息技术选修:算法与程序设计》第五章,原教材的编排是以本节以斐波那契的兔子问题引人,导出递归算法,从而自 定义了一个以递归方式解决的函数过程。然后利用子过程解决汉诺塔的经典问题。 教材经处理后,让同学们玩汉诺塔的游戏,导入递归问题,从用普通程序解决斐波那契的兔子问题入手,引导学生用自定义了一个以递归方式解决的函数过程解决问题,同时让同学们做三个递归练习,巩固提高。然后让学生做练习⑵ 和练习

递归算法详解

递 归 冯文科 一、递归的基本概念。 一个函数、概念或数学结构,如果在其定义或说明内部直接或间接地出现对其本身的引 用,或者是为了描述问题的某一状态,必须要用至它的上一状态,而描述上一状态,又必须用到它的上一状态……这种用自己来定义自己的方法,称之为递归或递归定义。在程序设计中,函数直接或间接调用自己,就被称为递归调用。 二、递归的最简单应用:通过各项关系及初值求数列的某一项。 在数学中,有这样一种数列,很难求出它的通项公式,但数列中各项间关系却很简单,于是人们想出另一种办法来描述这种数列:通过初值及n a 与前面临近几项之间的关系。 要使用这样的描述方式,至少要提供两个信息:一是最前面几项的数值,一是数列间各项的关系。 比如阶乘数列 1、2、6、24、120、720…… 如果用上面的方式来描述它,应该是: ???>==-1 ,1,11n na n a n n 如果需要写一个函数来求n a 的值,那么可以很容易地写成这样:

这就是递归函数的最简单形式,从中可以明显看出递归函数都有的一个特点:先处理一 些特殊情况——这也是递归函数的第一个出口,再处理递归关系——这形成递归函数的第二个出口。 递归函数的执行过程总是先通过递归关系不断地缩小问题的规模,直到简单到可以作为 特殊情况处理而得出直接的结果,再通过递归关系逐层返回到原来的数据规模,最终得出问题的解。 以上面求阶乘数列的函数)(n f 为例。如在求)3(f 时,由于3不是特殊值,因此需要计 算)2(*3f ,但)2(f 是对它自己的调用,于是再计算)2(f ,2也不是特殊值,需要计算 )1(*2f ,需要知道)1(f 的值,再计算)1(f ,1是特殊值,于是直接得出1)1(=f ,返回上 一步,得2)1(*2)2(==f f ,再返回上一步,得62*3)2(*3)3(===f f ,从而得最终解。 用图解来说明,就是 下面再看一个稍复杂点的例子。 【例1】数列}{n a 的前几项为

3.2.8递归函数程序设计 - 递归函数程序设计_实验项目

实验项目一 1.实验名称:求斐波那契数列项 2.实验目的: (1)熟练掌握递归函数的定义、实现与调用方法。 (2)熟练掌握循环与分支结构。 3.实验任务 (1)实验内容:编写求斐波那契数列项的函数,返回值为第n项值。斐波那契数列的定义为: f(0)=0,f(1)=1 f(n)=f(n-2)+f(n-1) (n>1) (2)实验要求:输入正整数n,输出斐波那契数列前n项,每行5个。要求用递归方法,并写出相应的主函数。 测试案例: 4.实验分析 (1)问题分析:问题的定义本身就是一个递归表示法: 递归出口:f(0)=0,f(1)=1 递归公式:f(n)=f(n-2)+f(n-1) (n>1) 有了这2个关键点,程序变得简单。 (2)实现要点:用函数fib(n)表示第n项斐波那契数列值,主函数循环调用fib(i),便可产生斐波那契数列前n项。 5.实验思考题 请比较递推法和递归法实现的不同。 实验项目二 1.实验名称:将正整数n转换为二进制 2.实验目的: (1)熟练掌握递归思想。 (2)熟练掌握递归函数的定义、实现与调用方法。 3.实验任务 (1)实验内容:输入1 个正整数n,将其转换为二进制后输出。 (2)实验要求:要求定义并调用函数 dectobin(n),它的功能是输出 n 的二进制。

测试案例: 4.实验分析 (1)问题分析:首先应了解手工计算的过程。通过不断整除2得到余数,直到商为零为止,将得到的余数系列逆序输出,即为转换的二进制数。 (2)实现要点:对于递归程序设计的2个关键点: 递归式:不断除2,输出余数 递归出口:商为0 余数系列逆序输出解决方法:先递归调用,再输出,dectobin(n)= dectobin(n/2)+输出(n %2)。由于是先递归,再输出,因此递归会不断深入直到出口为止,然后返回回来后才能输出,达到了逆序的目的。 5.实验思考题 如何将本例推广到任意进制数的转换输出。 实验项目三 改正下列程序中的错误,输入一个整数n (n 0)和一个双精度浮点数x,输出函数P(n,x)的值(保留2位小数)。 1 (n=0) P(n, x) = x (n=1) ((2n-1)*P(n-1,x)-(n-1)*P(n-2,x))/n (n>1) 输入输出示例 Enter n, x: 10 1.7 P(10,1.70) = 3.05 源程序(有错误的程序) #include int main(void) { int n; double x, result; printf(“Enter n, x: ”); scanf("%d%lf", &n, &x); result = p(n,x); printf("P(%d,%.2lf) = %.2lf\n", n, x, result); return 0; } double p(int n, double x) {

高中信息技术 算法与程序设计-递归算法的实现教案 教科版

递归算法的实现 【基本信息】 【课标要求】 (三)算法与问题解决例举 1. 内容标准 递归法与问题解决 (1)了解使用递归法设计算法的基本过程。 (2)能够根据具体问题的要求,使用递归法设计算法、编写递归函数、编写程序、求解问题。 【教材分析】 “算法的程序实现”是《算法与程序设计》选修模块第三单元的内容,本节课是“递归算法的程序实现”,前面学习了用解析法解决问题、穷举法解决问题、在数组中查找数据、对数进行排序以及本节的前一小节知识点“什么是自定义函数”的学习,在学习自定义函数的基础上,学习递归算法的程序实现是自定义函数的具体应用,培养学生“自顶向下”、“逐步求精”的意识起着重要的作用。 『递归算法在算法的学习过程中是一个难点,在PASCAL和C语言等程序语言的学习过程中,往往是将其放在“函数与过程”这一章节中来讲解的。递归算法的实现也是用函数或是过程的自我调用来实现的。从这一点上来讲,作者对教材的分析与把握是准确的,思路是清晰的,目标是明确的。』 【学情分析】 教学对象是高中二年级学生,前面学习了程序设计的各种结构,在学习程序设计各种结构的应用过程中培养了用计算机编程解决现实中问题的能力,特别是在学习循环语句的过程中,应用了大量的“递推”算法。前一节课学习了如何自定义函数,在此基础上学习深入学习和体会自定义函数的应用。以递推算法的逆向思维进行求解问题,在学习过程中体会递归算法的思想过程。多维度的思考问题和解决问题是提高学生的学习兴趣关键。 『递归算法的本质是递推,而递推的实现正是通过循环语句来完成的。作者准确把握了学生前面的学习情况,对递归算法的本质与特征也分析的很透彻,可以说作者对教学任务的分析是很成功的,接来就要看,在成功分析的基础上作者是如何通过设计教学来解决教学难点的了。』 【教学目标】

递归算法详解完整版

递归算法详解标准化管理处编码[BBX968T-XBB8968-NNJ668-MM9N]

递归 冯文科一、递归的基本概念。 一个函数、概念或数学结构,如果在其定义或说明内部直接或间接地出现对其本身的引用,或者是为了描述问题的某一状态,必须要用至它的上一状态,而描述上一状态,又必须用到它的上一状态……这种用自己来定义自己的方法,称之为递归或递归定义。在程序设计中,函数直接或间接调用自己,就被称为递归调用。 二、递归的最简单应用:通过各项关系及初值求数列的某一项。 在数学中,有这样一种数列,很难求出它的通项公式,但数列中各项间关系却很简 a与前面临近几项之间的关单,于是人们想出另一种办法来描述这种数列:通过初值及 n 系。 要使用这样的描述方式,至少要提供两个信息:一是最前面几项的数值,一是数列间各项的关系。 比如阶乘数列 1、2、6、24、120、720…… 如果用上面的方式来描述它,应该是: a的值,那么可以很容易地写成这样: 如果需要写一个函数来求 n

这就是递归函数的最简单形式,从中可以明显看出递归函数都有的一个特点:先处理一些特殊情况——这也是递归函数的第一个出口,再处理递归关系——这形成递归函数的第二个出口。 递归函数的执行过程总是先通过递归关系不断地缩小问题的规模,直到简单到可以作为特殊情况处理而得出直接的结果,再通过递归关系逐层返回到原来的数据规模,最终得出问题的解。 以上面求阶乘数列的函数) f为例。如在求)3(f时,由于3不是特殊值,因此需 (n 要计算)2( 3f,但)2(f是对它自己的调用,于是再计算)2(f,2也不是特殊值,需要计 * 算)1( f,返回 )1(= 2f,需要知道)1(f的值,再计算)1(f,1是特殊值,于是直接得出1 * 上一步,得2 3 * )2( )3(= = f,从而得最终 =f )1( 3 2 * * )2(= =f 2 f,再返回上一步,得6 解。 用图解来说明,就是

函数的递归调用与分治策略

函数的递归调用与分治策 略 This manuscript was revised on November 28, 2020

函数的递归调用与分治策略 递归方法是算法和程序设计中的一种重要技术。递归方法即通过函数或过程调用自身将问题转化为本质相同但规模较小的子问题。递归方法具有易于描述和理解、证明简单等优点,在动态规划、贪心算法、回溯法等诸多算法中都有着极为广泛的应用,是许多复杂算法的基础。递归方法中所使用的“分而治之”的策略也称分治策略。 递归方法的构造 构造递归方法的关键在于建立递归关系。这里的递归关系可以是递归描述的,也可以是递推描述的。下面由一个求n的阶乘的程序为例,总结出构造递归方法的一般步骤。 [例1]从键盘输入正整数N(0<=N<=20),输出N!。 [分析]N!的计算是一个典型的递归问题。使用递归方法来描述程序,十分简单且易于理解。 [步骤1]描述递归关系递归关系是这样的一种关系。设{U1,U2,U3,…,Un…}是一个序列,如果从某一项k开始,Un和它之前的若干项之间存在一种只与n有关的关系,这便称为递归关系。 注意到,当N>=1时,N!=N*(N-1)!(N=1时,0!=1),这就是一种递归关系。对于特定的K!,它只与K与(K-1)!有关。 [步骤2]确定递归边界在步骤1的递归关系中,对大于k的Un的求解将最终归结为对Uk的求解。这里的Uk称为递归边界(或递归出口)。在本例中,递归边界为k=0,即0!=1。对于任意给定的N!,程序将最终求解到0!。 确定递归边界十分重要,如果没有确定递归边界,将导致程序无限递归而引起死

循环。例如以下程序: #include <> int f(int x){ return(f(x-1)); } main(){ cout<=1时 n!= 1 当N=0时 再将这种关系翻译为代码,即一个函数: long f(int n){ if (n==0) return(1); else return(n*f(n-1)); } [步骤4]完善程序主要的递归函数已经完成,将程序依题意补充完整即可。

(重要)递归(含代码执行过程解释)

递归算法详细分析-> C阅读(17418) C通过运行时堆栈支持递归函数的实现。递归函数就是直接或间接调用自身的函数。 许多教科书都把计算机阶乘和菲波那契数列用来说明递归,非常不幸我们可爱的著名的老潭老师的《C语言程序设计》一书中就是从阶乘的计算开始的函数递归。导致读过这本经书的同学们,看到阶乘计算第一个想法就是递归。但是在阶乘的计算里,递归并没有提供任何优越之处。在菲波那契数列中,它的效率更是低的非常恐怖。 这里有一个简单的程序,可用于说明递归。程序的目的是把一个整数从二进制形式转换为可打印的字符形式。例如:给出一个值4267,我们需要依次产生字符‘4’,‘2’,‘6’,和‘7’。就如在printf函数中使用了%d格式码,它就会执行类似处理。 我们采用的策略是把这个值反复除以10,并打印各个余数。例如,4267 除10的余数是7,但是我们不能直接打印这个余数。我们需要打印的是机器字符集中表示数字‘7’的值。在ASCII码中,字符‘7’的值是55,所以我们需要在余数上加上48来获得正确的字符,但是,使用字符常量而不是整型常量可以提高程序的可移植性。‘0’的ASCII码是48,所以我们用余数加上‘0’,所以有下面的关系: ‘0’+ 0 =‘0’ ‘0’+ 1 =‘1’ ‘0’+ 2 =‘2’ ... 从这些关系中,我们很容易看出在余数上加上‘0’就可以产生对应字符的代码。接着就打印出余数。下一步再取商的值,4267/10等于426。然后用这个值重复上述步骤。 这种处理方法存在的唯一问题是它产生的数字次序正好相反,它们是逆向打印的。所以在我们的程序中使用递归来修正这个问题。 我们这个程序中的函数是递归性质的,因为它包含了一个对自身的调用。乍一看,函数似乎永远不会终止。当函数调用时,它将调用自身,第2次调用还将调用自身,以此类推,似乎永远调用下去。这也是我们在刚接触递归时最想不明白的事情。但是,事实上并不会出现这种情况。 这个程序的递归实现了某种类型的螺旋状while循环。while循环在循环体每次执行时必须取得某种进展,逐步迫近循环终止条件。递归函数也是如此,它在每次递归调用后必须越来越接近某种限制条件。当递归函数符合这个限制条件时,它便不在调用自身。

实验7-2-函数调用

实验7-2 函数(二) 1 【实验目的】 (1)掌握函数的嵌套调用的方法 (2)掌握函数的递归调用的方法 (3)掌握全局变量和局部变量的概念和用法 【实验要求】 (1)熟练掌握函数的嵌套调用的方法 (2)熟练掌握函数的递归调用的方法 【实验环境】 (1) Microsoft XP操作系统 (2) Microsoft VC++ 6.0 【实验内容】 1、素数https://www.doczj.com/doc/3c4331895.html,/acmhome/problemdetail.do?&method=showdetail&id=1098描述:输出100->200之间的素数的个数,以及所有的素数。 输入:无 输出:100->200之间的素数的个数,以及所有的素数。 样例输入:无 样例输出:

21 101 103 ... 197 199 2、字符串逆序https://www.doczj.com/doc/3c4331895.html,/JudgeOnline/problem.php?id=1499 题目描述:写一函数,使输入的一个字符串按反序存放,在主函数中输入输出反序后的字符串。 输入:一行字符 输出:逆序后的字符串 样例输入:123456abcdef 样例输出:fedcba654321 3、字符串拼接https://www.doczj.com/doc/3c4331895.html,/JudgeOnline/problem.php?id=1500 题目描述:写一函数,将两个字符串连接 输入:两行字符串 输出:链接后的字符串 样例输入: 123 abc 样例输出 123abc 4、输出元音https://www.doczj.com/doc/3c4331895.html,/JudgeOnline/problem.php?id=1501

深入理解递归函数.docx

深入理解递归函数 刚开始接触编程对递归调用都是比较头痛,很多年前我也会一样。昨天晩上睡觉突然想起了谭浩强C语言的汉诺塔递归调用,记得当吋是在高中的时候,我表姐在上大学,她把谭浩强的C语言给了我,只看书不实践,现在想起来效果还真差。其中递归调用汉诺塔看了好久都没有整明白,直到上大学学习C语言也还没有搞明白,当学到递归调用了,我就去问老师,老是说回去看看,下周告诉我。谁知到老师真的很忙,下周也没有结果。后来自己什么吋候明白的也忘记了。 刚开始接触递归都会告诉你,递归占用资源,使程序复杂,最好不要使用;还有人说,如果这个人一来就是用递归,我肯定不会聘用他。但是我认为这些观点太片面。递归算法的目的降低程序的复杂度,解放大脑负担,让大脑更加专注于问题本身。程序的性能跟递归没有什么关系,更重要的时算法本身,我们会在稍后讲解一下同i种算法同样是递归,性能的差异巨大。设计模式中,很多模式都存在递归。 刚开始接触递归的,往往都会在里面打圈圈,自己越绕越晕,觉得递归太复杂。其实看待递归的时候,也是要分层面看待,不要把自己的大脑当做是电脑,可以绕很多的圈圈,有人说人的大脑同时能处理7个左右的变量,绕一圈就多几个变量,能绕几圈啊。呵呵。找到一个算法,在编写算法的吋候,只考虑一次递归所做的事情,如果遇到到递归调用函数的时候,把他当做一个函数整体考虑,他能完成他要完成的事情,要相信他,也要相信自己。我们所在的层面就是算法的层面,或者一次执行的层面。如果在算法层面和递归调用层面来回穿插的思考,读懂递归算法将非常困难,递归的复杂度就在于压栈会导致大量的变量需要存储,对我们的大脑来说负担太重,但是对汁算机来说是小意思,相对来说算法层面往往很简单,所以我们一定要站在算法层面考虑问题,而不是递归层面。 下面来看我如何一步一步实现汉诺塔:(VS2010C#控制台程序) [csharp] view plaincopyprint^C 1.class Program 2?{ 3?static void Main(string[] args) 4.<

C语言函数递归[1]

递归,作为C语言最经典的算法之一,是一种非常有用的程序设计方法。虽然用递归算法编写的程序结构清晰,具有很好的可读性,还往往使某些看起来不易解决的问题变得容易解决。但在递归函数中,由于存在着自调用过程,程序控制反复进入其自身,使程序的分析设计有一定困难,致使很多初学者往往对递归迷惑不解,也在这上面花了不少的时间,却收效甚微。那么,究竟什么是递归?怎么实现递归呢? 所谓递归,简而言之就是在调用一个函数的过程中又直接或间接地调用该函数本身,以实现层次数据结构的查询和访问。在函数中直接调用函数本身,称为直接递归调用。在函数中调用其它函数,其它函数又调用原函数,这就构成了函数自身的间接调用,称为间接递归调用。 而采用递归方法来解决问题,必须符合以下三个条件: 1、可以把要解决的问题转化为一个新问题,而这个新的问题的解决方法仍与原来的解决方法相同,只是所处理的对象有规律地递增或递减。 说明:解决问题的方法相同,调用函数的参数每次不同(有规律的递增或递减),如果没有规律也就不能适用递归调用。 2、可以应用这个转化过程使问题得到解决。 说明:使用其他的办法比较麻烦或很难解决,而使用递归的方法可以很好地解决问题 3、必定要有一个明确的结束递归的条件。 说明:一定要能够在适当的地方结束递归调用。不然可能导致系统崩溃。 好知道是这样以后;我们来写一个众多教材上的程序:使用递归的方法求n!。 当n>1时,求n!的问题可以转化为n*(n-1)!的新问题。比如n=4: 第一部分:4*3*2*1 n*(n-1)! 第二部分:3*2*1 (n-1)(n-2)! 第三部分:2*1 (n-2)(n-3)! 第四部分:1 (n-4)! 4-4=0,得到值1,结束递归。 我给的源程序如下: #include int fac(int n) {int c; printf("now the number is %d ",n); getchar(); if(n==1 || n==0) c=1; else c=n*fac(n-1); printf("now the number is %d and the %d! is %d",n,n,c); getchar();

递归下降语法分析程序的设计说明

编译方法实验报告实验名称:简单的语法分析程序设计

实验要求 1.功能:对简单的赋值语句进行语法分析 随机输入赋值语句,输出所输入的赋值语句与相应的四元式 2.采用递归下降分析程序完成(自上而下的分析) 3.确定各个子程序的功能并画出流程图 4.文法如下:

5.编码、调试通过 采用标准输入输出方式。输入输出的样例如下: 【样例输入】 x:=a+b*c/d-(e+f) 【样例输出】(说明,语句和四元式之间用5个空格隔开) T1:=b*c (*,b,c,T1) T2:=T1/d (/,T1,d,T2) T3:=a+T2 (+,a,T2,T3) T4:=e+f (+,e,f,T4) T5:=T3-T4 (-,T3,T4,T5) x:=T5 (:=,T5,-,x) 【样例说明】程序除能够正确输出四元式外,当输入的表达式错误时,还应能检测出语法错误,给出相应错误提示。 6.设计3-5个赋值语句测试实例,检验程序能否输出正确的四元式;当输入错误的句子时, 检验程序能够给出语法错误的相应提示信息。 7.报告容包括: 递归程序的调用过程,各子程序的流程图和总控流程图,详细设计,3-5个测试用例的程序运行截图及相关说明,有详细注释的程序代码清单等。

目录 1.语法分析递归下降分析算法 (5) 1.1背景知识 (5) 1.2消除左递归 (6) 2.详细设计及流程图 (6) 2.1 函数void V( ) // V -> a|b|c|d|e...|z . (6) 2.2 函数void A( ) // A -> V:=E (7) 2.3 函数void E() //E -> TE' (7) 2.4函数void T( ) // T -> FT' (8) 2.5函数void E1( ) //E'-> +TE'|-TE'|null (8) 2.6函数void T1() // T'-> *FT'|/FT'|null (9) 3.测试用例及截图 (9) 3.1测试用例1及截图 (9) 3.2测试用例2及截图 (10) 3.3测试用例3及截图 (11) 代码清单 (11)

什么是递归函数

1.什么是递归函数(recursive function) 递归函数即自调用函数,在函数体内部直接或间接地自己调用自己,即函数的嵌套调用是函数本身。 例如,下面的程序为求n!: long fact(int n) { if(n==1) return1; return fact(n-1)*n;//出现函数自调用 } 2.函数调用机制的说明 任何函数之间不能嵌套定义,调用函数与被调用函数之间相互独立(彼此可以调用)。发生函数调用时,被调函数中保护了调用函数的运行环境和返回地址,使得调用函数的状态可以在被调函数运行返回后完全恢复,而且该状态与被调函数无关。 被调函数运行的代码虽是同一个函数的代码体,但由于调用点,调用时状态,返回点的不同,可以看作是函数的一个副本,与调用函数的代码无关,所以函数的代码是独立的。被调函数运行的栈空间独立于调用函数的栈空间,所以与调用函数之间的数据也是无关的。函数之间靠参数传递和返回值来联系,函数看作为黑盒。 这种机制决定了C/C++允许函数递归调用。 3.递归调用的形式 递归调用有直接递归调用和间接递归调用两种形式。 直接递归即在函数中出现调用函数本身。 例如,下面的代码求斐波那契数列第n项。斐波那契数列的第一和第二项是1,后面每一项是前二项之和,即1,1,2,3,5,8,13,...。代码中采用直接递归调用: long fib(int x) { if(x>2) return(fib(x-1)+fib(x-2));//直接递归 else return1; } 间接递归调用是指函数中调用了其他函数,而该其他函数却又调用了本函数。例如,下面的代码定义两个函数,它们构成了间接递归调用: int fnl(int a) { int b; b=fn2(a+1);//间接递归 //...

递归算法详解

递归算法详解 C通过运行时堆栈支持递归函数的实现。递归函数就是直接或间接调用自身的函数。 许多教科书都把计算机阶乘和菲波那契数列用来说明递归,非常不幸我们可爱的著名的老潭老师的《C语言程序设计》一书中就是从阶乘的计算开始的函数递归。导致读过这本经书的同学们,看到阶乘计算第一个想法就是递归。但是在阶乘的计算里,递归并没有提供任何优越之处。在菲波那契数列中,它的效率更是低的非常恐怖。 这里有一个简单的程序,可用于说明递归。程序的目的是把一个整数从二进制形式转换为可打印的字符形式。例如:给出一个值4267,我们需要依次产生字符‘4’,‘2’,‘6’,和‘7’。就如在printf函数中使用了%d格式码,它就会执行类似处理。 我们采用的策略是把这个值反复除以10,并打印各个余数。例如,4267除10的余数是7,但是我们不能直接打印这个余数。我们需要打印的是机器字符集中表示数字‘7’的值。在ASCII码中,字符‘7’的值是55,所以我们需要在余数上加上48来获得正确的字符,但是,使用字符常量而不是整型常量可以提高程序的可移植性。‘0’的ASCII码是48,所以我们用余数加上‘0’,所以有下面的关系: ‘0’+ 0 =‘0’ ‘0’+ 1 =‘1’ ‘0’+ 2 =‘2’ ... 从这些关系中,我们很容易看出在余数上加上‘0’就可以产生对应字符的代码。接着就打印出余数。下一步再取商的值,4267/10等于426。然后用这个值重复上述步骤。 这种处理方法存在的唯一问题是它产生的数字次序正好相反,它们是逆向打印的。所以在我们的程序中使用递归来修正这个问题。 我们这个程序中的函数是递归性质的,因为它包含了一个对自身的调用。乍一看,函数似乎永远不会终止。当函数调用时,它将调用自身,第2次调用还将调用自身,以此类推,似乎永远调用下去。这也是我们在刚接触递归时最想不明白的事情。但是,事实上并不会出现这种情况。 这个程序的递归实现了某种类型的螺旋状while循环。while循环在循环体每次执行时必须取得某种进展,逐步迫近循环终止条件。递归函数也是如此,它在每次递归调用后必须越来越接近某种限制条件。当递归函数符合这个限制条件时,它便不在调用自身。 在程序中,递归函数的限制条件就是变量quotient为零。在每次递归调用之前,我们都把quotient除以10,所以每递归调用一次,它的值就越来越接近零。当它最终变成零时,递归便告终止。 /*接受一个整型值(无符号0,把它转换为字符并打印它,前导零被删除*/

【习题】函数调用Word版

函数调用 【实验目的】: 1. 掌握函数的定义和调用方法。 2. 练习重载函数的使用。 3. 练习有默认参数值的函数的使用。 4. 练习使用系统函数。 5. 熟悉多文件工程结构。 【实验内容】: 1.编写函数int add(int x, int y),实现两个整型数据x,y的求和功能。 ·要求:使用Visual C++的Debug调试功能,记录在函数调用时实参和形参的值 的变化。 2.编写一个求x的n次方的程序int pow(int m, int n),计算m的n次方的结果。 3.利用上题中设计两个函数,设计一个求两个整数的平方和的程序。要求如下: a)主函数中调用求和函数: int add(int x, int y);

求和函数add中调用上题设计的int pow(int m, int n)函数来计算其平方。 4.多文件程序结构:一个文件可以包含多个函数定义,但是一个函数的定义必须完 整的存在于一个文件中。要求: a)将add函数的声明部分放在头文件(add.h)中,实现部分放在源文件(add.cpp) 中。 b)将pow函数的声明部分放在头文件(pow.h)中,实现部分放在源文件(pow.cpp) 中。 c)在main函数中调用add函数,计算从屏幕终端输入的两个数据之和。(main 函数的实现在main.cpp中) 5.将第2题设计的pow函数修改成为递归函数。

6.设计一个函数int fac(int n),利用函数的递归调用,来计算n!(n的阶乘)。 ·要求:单步调试程序,记录递归函数的调用过程。 7.使用系统函数pow(x,y)计算x y的值,注意包含头文件cmath。 8.从键盘输入两个数字,分别赋值给变量a、b,设计一个子函数swap,实现这两个数字交换次序。(注:根据需要自己设计函数的参数及返回值) ·要求:使用Visual C++的Debug调试功能,记录在函数调用时实参和形参的值的变化。 9.设计一个函数,求圆的面积。 要求:在主函数中调用子函数calArea计算圆的面积。并将calArea函数设计为内联函数。

递归程序设计 求N阶乘

(一)实验名称 递归程序设计求N阶乘 (二)实验内容和要求 设计一个汇编程序完成y=n!的计算。 要求:(1)能够根据用户输入的n值计算其阶乘,结果以十进制数显示; (2)基于递归程序结构,模块划分合理,具有清晰的入口和出口。(三)实验目的 (1)感受和学习递归程序的设计方法、技巧,完成递归程序设计 (2)学会运用堆栈传递参数的方法和技巧 (3)进一步感受和学习汇编语言程序设计的方法、技巧和调试过程(四)实验日期、时间和地点 时间:2010年11月22日 地点:微机高级实验室 (五)实验环境(说明实验用的软硬件环境及调试软件) 使用masm for windows (六)实验步骤(只写主要操作步骤,要简明扼要,还应该画出程序流程图或实验电路的具体连接图)

(七)实验结果(经调试通过的源程序的所有代码,应包含必要的说明文字)DATAS SEGMENT OPE DW 0,0,0,0 RESULT DB 16 DUP(0),'H',0DH,0AH,0AH,'$' NUM DB 3,0,3 DUP(0) MESS1 DB'Please input N(key Enter to quit):',0DH,0AH,'$' ERR_MESS DB'Error number,try again!',0DH,0AH,0AH,'$' FUNC DB 0,0,'!','=','$' DATAS ENDS STACKS SEGMENT STACK DW 1000 DUP(?) STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS DS_STR MACRO BUF ;显示字符串的宏 PUSH DX PUSH AX LEA DX,BUF MOV AH,09H INT 21H POP AX POP DX ENDM ;—————————————————————————————————— ————

数据结构实验:递归程序设计-精简

实验名称:实验六递归程序设计(实验报告) 一.实验目的: 1. 理解递归程序设计基本方法 2.理解递归的三大要素 二.实验内容: 1. 根据整数乘法运算的特点,给出整数乘法运算的递归实现 2、编写一个递归实现整数之间乘法运算的函数,并进行测试,验证设计的正确性。 二、实验原理: 1、什么是递归: 在定义一个过程或函数时出现调用本过程或本函数的成分,称之为递归。若调用自身,称之为直接递归。若过程或函数p调用过程或函数q,而q又调用p,称之为间接递归。 如果一个递归过程或递归函数中递归调用语句是最后一条执行语句,则称这种递归调用为尾递归。 2、以下三种情况使用递归: 2.1、问题的定义是递归的。 2.2、数据结构是递归的。 2.3、问题求解的过程是递归的。 3、递归算法的设计方法: 先将整个问题划分为若干个子问题,通过分别求解子问题,最后获得整个问题的解。而这些子问题具有与原问题相同的求解方法,于是可以再将它们划分成若干个子问题,分别求解,如此反复进行,直到不能再划分成子问题,或已经可以求解为止。 4.递归算法的执行过程: 4.1递归算法的执行过程是不断地自调用,直到到达递归出口才结束自调用过程; 4.2到达递归出口后,递归算法开始按最后调用的过程最先返回的次序返回; 4.3返回到最外层的调用语句时递归算法执行过程结束。 2.实验流程: 1、编辑主函数并初始化优先级队列; 2、通过函数调用完成程序设计; 3、运行编译函数,查看结果 四.程序代码: 1.主程序 #include "stdio.h"

mult(int x,int y) { if (y==1) return x; else return x+mult(x,y-1); } void main() { int j,k,m; printf("请输入两个乘数:\n"); scanf("%d %d",&j,&k); printf("结果为:\n"); m=mult(j,k); printf("%d",m); printf("\n"); } } 2.实验结果: 结果分析:由实验结果可知,成功的完成了对递归的操作,可见能实现乘数的功能实现,实验基本成功。 五.心得体会: 在本次试验中,主要是熟悉对递归操作,虽然这些操作的基本原理都比较熟悉,但是实际上机时还是出现了不少问题,但是有与编程能力太差,还有时间问题,所以实验不是很成功,对递归概念还是有些不清楚,所以还要再接再厉,争取有更多的收获。

探讨递归方法及其计算机实现

探讨递归方法及其计算机实现 摘要:随着计算机技术的快速发展,数学知识在计算机技术发展中,尤其是在计算机应用程序设计中处于极其重要的地位.同时,用数学的思维解决各种程序设计方面的难题也是十分重要的.从方法论意义上说,递归方法是一种从简单到复杂、从低级到高级的可连续操作的解决问题的方法。它的每一步骤都是能行可操作的,并且各步骤之间是连续转换的。本文就递归算法在程序学习中的作用及使用范围进行探讨,并对计算机的递归方法进行了阐述,通过实例说明数学递归问题的计算机实现。 关键词:递归方法;递归算法;程序设计;计算机实现 一、前言 众所周知,数学在计算机科学技术的发展中有不可替代的重要作用,如何将一个面临的实际问题转化为当前计算机系统能够处理的问题,数学理论知识在计算机上的实现是使计算机成为很好的新型数学工具的关键所在。而递归是程序设计中非常重要的内容,绝大部分程序设计语言都涉及到用递归解决问题。本文以递归算法为例,综述讲解了其在计算机基础学科中的知识要点,就递归算法在程序学习中的作用及使用范围进行探讨,以深化对该部分知识的掌握及运用。 二、递归方法 所谓递归是指借助于“回归”而把未知的归结为已知的。而递归函数是一种数论函数,就是说这种函数的定义域和值域都是自然数,并且对未知数值的计算往往是要回归到已知数值才能求出。递归是一种循环结构,它把“较复杂”情形的计算,递次地归结为“较简单”情形的计算,一直归结到“最简单”情形的计算,并得到计算结果为止。这就是递归的实质。对于定义是递归的,数据结构是递归的,问题的解法是递归的,都可以采用递归方法来处理。 递归论又称为“递归函数论”、“能行性理论”。各种递归函数本身的构造也是它研究的重要方面。递归论所研究的数论函数有精确的数学定义。为示例起见,用递归定义式定义“斐波那契函数”如下: 初始规定: f(0)=0, f(1)=l, 递归运算关系: f(n)=f(n一1)+f(n一2)。 容易看到,任意给定一个自然数n,f(n)恒可使用上述递归定义式逐步地求得。 从一般意义上说,递归定义是用简单的、自明的要素描述、构造、说明复杂的整体。递归方法是通过解决简单的问题来解决复杂的问题。在人们的思维过程,存在着递归机制。对于某些问题必须用递归方法来定义或解决。 在各种科学领域中以至在社会结构中、人们的各种操作行为中,普遍存在一类具有递归结构的问题,我们把这类问题称为“递归问题”。递归方法就是解决这类“递归问题”的精确方法。 三、递归算法 1、递归算法的基本问题:斐波那契数列

用递归法解决问题

用递归法解决问题 一、教材分析 “算法的程序实现”是高中信息技术教育出版社《算法与程序设计》选修模块第三单元的内容,本节课是“递归算法的程序实现”,前面学习了用解析法解决问题、穷举法解决问题、在数组中查找数据、对数进行排序以及本节的前一小节知识点“什么是自定义函数”的学习,,在学习自定义函数的基础上,学习递归算法的程序实现是自定义函数的具体应用,培养学生“自顶向下”、“逐步求精”的意识起着重要的作用。 课时安排:1课时 二、学情分析 教学对象是高中二年级学生,前面学习了程序设计的各种结构,在学习程序设计各种结构的应用过程中的培养了用计算机编程解决现实中的问题,特别的学习循环语句的过程中,应用了大量的“递推”算法。前一节课学习了如何自定义函数,在此基础上学习深入学习和体会自定义函数的应用。以递推算法的逆向思维进行求解问题,在学习过程中体会递归算法的思想过程。多维度的思考问题和解决问题是提高学生的学习兴趣关键。 三、教学目标 知识与技能: 1、理解什么是递归算法,学生用递归算法的思想分析问题 2、能够应用自定义函数方法实现递归算法的编程 过程与方法: 学生参与讨论,通过思考、动手操作,体验递归算法的方法 情感态度与价值: 结合数学中的实例,激发学生的数学建模的意识,培养学生多维度的思考问题和解决问题。 四、教学重点·难点 重点:理解什么是递归算法,学生用递归算法的思想分析问题 应用自定义函数方法实现递归算法的编程 难点:应用自定义函数方法实现递归算法的编程 五、教学过程

六、教学反思 从游戏的方式导入活动,充分的调动学生的思维,渐渐的走入了“递归的思维”模式,从而引出“猴子吃桃”,使用的前面活动(礼物是什么?)的思维,诱导学生进入了“递归”思想解题。学生阅读教材范例“裴波那契”,培养学生的自学能力、和知识迁移建构自我的知识体系。内化递归算法的实现,再由递归思维的逆向思维讨论“递推”的算法,进行比较计算机资源的耗费高,可读性差。为下一步导出结论做好了铺垫。 学好本节课的前提是:懂得自定义函数的使用方法,如果学生对自定义函数理解程度,是本节课效果是否得以完成的关键

第十一讲 函数的递归调用及函数中的变量定义

第十一讲函数的递归调用及函数中的变量定义 一、函数的递归调用 1.递归的概念 直接递归调用:调用函数的过程中又调用该函数本身,自己调用自己。 间接递归调用:调用f1函数的过程中调用f2函数,而f2中又需要调用f1。 以上均为无终止递归调用。为了让这种调用终止,一般要用if语句来控制使递归过程到某一条件满足时结束。 2、递归法 类似于数学证明中的反推法,从后一结果与前一结果的关系中寻找其规律性。 递归法:从结果出发,归纳出后一结果与前一结果直到初值为止存在的关系 编程思想:设计一个函数(递归函数),这个函数不断使用下一级值调用自身,直到结果已知处——选择控制结构 其一般形式是: 递归函数名f (参数n) { if (n=初值) 结果=常量; else 结果=含f(x-1)的表达式; return 结果; } 例1.输入一个n,编写函数求n!,根据不同的算法,我们可以用三种方式。 方式一:用递推算法,Sn=n!的递推关系如下: 1 (n=1,0) Sn= Sn-1×n n>1 是一种累计乘积的关系,先得到上一个数的阶乘,然后再得到得到下个数的阶乘,用循环结构来实现。 程序代码如下: main()

{ int n; float sn; float fac(int ); /*函数的声明*/ printf("Input n="); scanf("%d",&n); sn=fac(n); /*函数的调用*/ printf("%d!=%.0f",n,sn); } float fac(int n) /*函数的定义*/ { float f=1.0; int i; if (n==0||n==1) return f; for(i=1;i<=n;i++) f=f*i; return f; } 方式二:用递归算法,f(n)=n!的递归求解关系如下: 1 (n=1,0) f(n)= f(n-1)×n n>1 递归程序分两个阶段执行—— ①回推(调用):欲求n! →先求 (n-1)! →(n-2)! →…→ 1! 若1!已知,回推结束。 ②递推(回代):知道1!→2!可求出→3!→…→ n! 注意:在此可画图来说明 程序清单如下: main() { int n; float sn; float fac(); /*函数的声明*/ clrscr(); printf("Input n=");

相关主题
文本预览
相关文档 最新文档