递归法教案

递归法教案
递归法教案

《用递归法解决问题》教案

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

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

递归与分治

分治算法 一、分治算法 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。 分治法解题的一般步骤: (1)分解,将要解决的问题划分成若干规模较小的同类问题; (2)求解,当子问题划分得足够小时,用较简单的方法解决; (3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。 当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。这就是分治策略的基本思想。下面通过实例加以说明。 【例1】[找出伪币] 给你一个装有1 6个硬币的袋子。1 6个硬币中有一个是伪造的,并且那个伪造的硬币比真的硬币要轻一些。你的任务是找出这个伪造的硬币。为了帮助你完成这一任务,将提供一台可用来比较两组硬币重量的仪器,利用这台仪器,可以知道两组硬币的重量是否相同。比较硬币1与硬币2的重量。假如硬币1比硬币2轻,则硬币1是伪造的;假如硬币2比硬币1轻,则硬币2是伪造的。这样就完成了任务。假如两硬币重量相等,则比较硬币3和硬币4。同样,假如有一个硬币轻一些,则寻找伪币的任务完成。假如两硬币重量相等,则继续比较硬币5和硬币6。按照这种方式,可以最多通过8次比较来判断伪币的存在并找出这一伪币。 另外一种方法就是利用分而治之方法。假如把1 6硬币的例子看成一个大的问题。第一步,把这一问题分成两个小问题。随机选择8个硬币作为第一组称为A组,剩下的8个硬币作为第二组称为B组。这样,就把1 6个硬币的问题分成两个8硬币的问题来解决。第二步,判断A和B组中是否有伪币。可以利用仪器来比较A组硬币和B组硬币的重量。假如两组硬币重量相等,则可以判断伪币不存在。假如两组硬币重量不相等,则存在伪币,并且可以判断它位于较轻的那一组硬币中。最后,在第三步中,用第二步的结果得出原先1 6个硬币问题的答案。若仅仅判断硬币是否存在,则第三步非常简单。无论A组还是B组中有伪币,都可以推断这1 6个硬币中存在伪币。因此,仅仅通过一次重量的比较,就可以判断伪币是否存在。

算法设计与分析:递归与分治法-实验报告

应用数学学院信息安全专业班学号姓名 实验题目递归与分治法 综合实验评分表

实验报告 一、实验目的与要求 1.掌握递归算法的设计思想 2.掌握分治法设计算法的一般过程 3.理解并掌握算法渐近时间复杂度的分析方法 二、实验内容 1、折半查找的递归算法 (1)源程序代码 #include #include using namespace std; int bin_search(int key[],int low, int high,int k) { int mid; if(low>high) return -1; else{ mid = (low+high) / 2; if(key[mid]==k) return mid; if(k>key[mid]) return bin_search(key,mid+1,high,k); else return bin_search(key,low,mid-1,k); } } int main() { int n , i , addr; int A[10] = {2,3,5,7,8,10,12,15,19,21}; cout << "在下面的10个整数中进行查找" << endl; for(i=0;i<10;i++){ cout << A[i] << " " ; } cout << endl << endl << "请输入一个要查找的整数" << endl; cin >> n; addr = bin_search(A,0,9,n);

if(-1 != addr) cout << endl << n << "是上述整数中的第" << addr << "个数" << endl; else cout << endl << n << "不在上述的整数中" << endl << endl; getchar(); return 0; } (2)运行界面 ①查找成功 ②查找失败

递归与分治实验报告

递归与分治实验报告 班级:计科1102 姓名:赵春晓学号:2011310200631 实验目的:进一步掌握递归与分治算法的设计思想,通过实际问题来应用递归与分治设计算法。 实际问题:1集合划分问题,2输油管道问题,3邮局选址问题,4整数因子分解问题,5众数问题。 问题1:集合划分 算法思想:对于n个元素的集合,可以划分为由m个子集构成的集合,例如{{1,2}{3,4}}就是由2个子集构成的非空子集。假设f(n,m)表示将n个元素划分成由m个子集构成的集合的个数。那么1)若m == 1 ,则f(n,m)= 1 ;2)若n == m ,则f(n,m)= 1 ;3)若不是上面两种情况则有下面两种情况构成:3.1)向n-1个元素划分成的m个集合里面添加一个新的元素,则有m*f(n-1,m)种方法;3.2)向n-1个元素划分成的m-1个集合里添加一个由一个元素形成的独立的集合,则有f(n-1,m-1)种方法。 实验代码: #include #include using namespace std ; int jihehuafen( int n , int m ) { if( m == 1 || n == m ) return 1 ; else return jihehuafen( n - 1 , m - 1 ) + m*jihehuafen( n - 1 , m ) ; } int main() { ifstream fin("C:/input.txt") ; ofstream fout("C:/output.txt") ; int N , M , num ; fin >> N >> M ; num = jihehuafen( N , M) ; fout << num << endl ; return 0 ; } 问题2:输油管道 算法思想:由于主管道由东向西铺设。故主管道的铺设位置只和各油井的y坐标有关。要使主管道的y坐标最小,主管道的位置y坐标应是各个油井y坐标的中位数。先用快速排序法把各个油井的y坐标排序,然后取其中位数再计算各个油

实验7-2-函数调用

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

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

实验1++递归与分治算法

淮海工学院计算机工程学院实验报告书 课程名:《算法分析与设计》 题目:实验1 递归与分治算法 班级: 学号: 姓名:

实验1 递归与分治算法 实验目的和要求 (1)进一步掌握递归算法的设计思想以及递归程序的调试技术; (2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。 (3)分别用蛮力法和分治法求解最近对问题; (4)分析算法的时间性能,设计实验程序验证分析结论。 实验内容 设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。 实验环境 Turbo C 或VC++ 实验学时 2学时,必做实验 数据结构与算法 核心源代码 蛮力法: #include #include #include int ClosestPoints(int x[ ], int y[ ], int n); int main() { int x[3],y[3]; printf("请输入各点的横坐标: "); for(int i=0;i<4;i++) { scanf("%d",&x[i]); } printf("请输入各点的纵坐标: "); for(int j=0;j<4;j++)

{ scanf("%d",&y[i]); } ClosestPoints(x,y,4); return 0; } int ClosestPoints(int x[ ], int y[ ], int n) { int index1, index2; //记载最近点对的下标 int d, minDist = 1000; //假设最大距离不超过1000 for (int i = 0; i < n - 1; i++) for (int j = i + 1; j < n; j++) //只考虑i<j的点对 { d =sqrt ((x[i]-x[j])* (x[i]-x[j]) + (y[i]-y[j])* (y[i]-y[j])); if (d < minDist) { minDist = d; index1 = i; index2 = j; } } cout<<"最近的点对是:"< #include const int n = 4; struct point //定义点的结构体 { int x, y; };

递归算法详解

递归算法详解 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,把它转换为字符并打印它,前导零被删除*/

算法分析与设计实验一递归与分治策略

实验一递归与分治策略 实验目的 1.了解并掌握递归的概念,递归算法的基本思想; 2.掌握分治法的基本思想方法; 3.了解适用于用分治法求解的问题类型,并能用递归或非递归的方式设计相应的分治法算法; 4.掌握分治法复杂性分析方法,比较同一个问题的递归算法与循环迭代算法的效率。预习与实验要求 1.预习实验指导书及教材的有关内容,掌握分治法的基本思想; 2.严格按照实验内容进行实验,培养良好的算法设计和编程的习惯; 3.认真听讲,服从安排,独立思考并完成实验。 实验原理 简单说来,当一个函数用它自己来定义时就称为递归。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。因此,在考虑使用递归算法编写程序时,应满足两点:1)该问题能够被递归形式描述;2)存在递归结束的边界条件。递归的能力在于用有限的语句来定义对象的无限集合。用递归思想写出的程序往往十分简洁易懂。一般说来,一个递归算法可以转换称为一个与之等效的非递归算法,但转换后的非递归算法代码将成倍地增加。 分治是一种被广泛应用的有效方法,它的基本思想是把最初的问题分解成若干子问题,然后在逐个解决各个子问题的基础上得到原始问题的解。所谓分治就是“分而治之”的意思。由于分解出的每个子问题总是要比最初的问题容易些,因而分治策略往往能够降低原始问题的难度,或者提高解决原始问题的效率。 根据如何由分解出的子问题求出原始问题的解,分治策略又可分为两种情形:第一,原始问题的解只存在于分解出的某一个子问题中,则只需要在原始问题的一个划分中求解即可;第二,原始问题的解需要由各个子问题的解再经过综合处理得到。无论是哪一种情况,分治策略可以较快地缩小问题的求解范围,从而加快问题求解的速度。 分治策略运用于计算机算法是,往往会出现分解出来的子问题与原始问题类型相同的现象,而与原问题相比,各个子问题的规模变小了,这刚好符合递归的特征。因此分治策略往往是和递归联系在一起的。

递归与分治策略

第2章递归与分治策略 实验2 分治算法的递归程序实现与时间复杂度测试 1. 实验目的 编程实现合并排序和快速排序算法,理解分治算法设计的基本思想、递归程序实现的基本方法,加深对分治算法设计与分析思想的理解。通过程序的执行时间测试结果,与理论上的时间复杂度结论进行对比、分析和验证。 2. 原理解析 分治算法的基本思想 分治算法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。分治算法设计的一般步骤包括: (1) 分解,将要解决的问题划分成若干规模较小的同类问题; (2) 求解,当子问题划分得足够小时,用较简单的方法解决; (3) 合并,按原问题的要求,将子问题的解逐层合并构成原问题的解。 分治法的基本设计范式如下: DivideAndConquer(data,n,solution) if(n≤SizeLimit) then DirectSolution(data,n,solution) else DivideInput(data,n,smallerSets,smallerSizes,numberSmaller) for i=1 to numberSmaller do DivideAndConquer(smallerSets[i],smallerSizes[i],smallerSol ution[i]) end for CombineSolutions(smallerSolution,numberSmaller,solution) end if

测试算法 不同问题的分治算法在分解与合并步骤可能有所不同,例如合并排序和快速排序这两个有代表性的分治算法中,合并排序算法没有分解、只有合并,快速排序算法没有合并、只有分解;这两个算法的计算时间分别取决于合并与分解步骤。这两个算法分别如下: 1、MergeSort(list, first, last) if first

用递归法解决问题

3.5用递归法解决问题 【教材分析】 “用递归法解决问题”是《算法与程序设计》第三章第5节的内容,学业水平测试对本节内容也达到了B级要求,本节内容是在学习了VB基础知识中的三种基本结构,并且学习了数组、用解析法和穷举法解决问题等算法。本节先后介绍了“什么是递归法”、“自定义函数”、以及应用自定义函数结合递归算法来解决问题实例。通过本节内容的学习可以培养学生分析和分解问题的能力。从教材的结构上看“自定义函数”和“递归算法”是独立的,可以分别讲解,但在使用时两者是相辅相成的。 【学情分析】 这节课的教学对象是高中二年级学生,已经学习了算法与程序设计VB中的一些基础知识,初步了解了算法的概念。特点是在学习循环结构的过程中,学生已经积累了一些“递归”和“穷举”的算法。但是学生对函数尤其是“自定义函数”非常陌生,而“自定义函数”和“递归法”是本册的学习重点,也是以后编程的重点。学习本节内容学生可以充分体会递归算法的思想过程,扩大原来的知识面,进一步认识程序设计的功能,进一步激发学生学习算法与程序设计的兴趣。 【教学目标】 1.知识与技能: 理解什么是递归法,会用递归法的思想分析和解决问题 理解什么是自定义函数,能应用自定义函数实现递归算法的编程 2.过程与方法 学生通过思考、探究,体验递归算法和发现问题与解决问题的步骤 3.情感态度与价值观 在建立数学模型中培养学生的抽象思维能力,培养学生多维度思考问题和解决能力。 树立多学科整合的思想意识,能够用联系的观点解决问题。 【教学重点】 理解什么是递归算法,学会用递归法的思想分析问题。 理解自定义函数的概念。 【教学难点】 用自定义函数和递归算法编写程序解决问题 【教学方法及策略】

C语言递归

递归,作为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.递归插入排序 Void insert_sort(type A[ ],int n) { int k; type a; n=n-1; if (n>0) { insert_sort(A,n); a=A[n]; k=n-1; while (k>=0)&&A[k]>a)) { A[k+1]=A[k]; k=k-1; } A[k+1]=a; } } 2.合并排序 public static void mergeSort(Comparable a[], int left, int right) { if (left void merge(Type c[],Type d[],int l,int m,int r) { int i = l,j = m + 1,k = l; while((i<=m)&&(j<=r)) { if(c[i]<=c[j]) { d[k++] = c[i++];

else { d[k++] = c[j++]; } } if(i>m) { for(int q=j; q<=r; q++) { d[k++] = c[q]; } } else { for(int q=i; q<=m; q++) { d[k++] = c[q]; } } } 3.快速排序 private static void qSort(int p, int r) { if (p= x) j--; if(i < j)

最近对问题_递归与分治算法

淮海工学院计算机工程学院 实验报告书 课程名:《算法分析与设计》 题目:实验1 递归与分治算法 最近对问题 班级:软件081班 学号:110831116 姓名:陈点点

实验1 递归与分治算法 一,实验目的和要求 (1)进一步掌握递归算法的设计思想以及递归程序的调试技术; (2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。 (3)分别用蛮力法和分治法求解最近对问题; (4)分析算法的时间性能,设计实验程序验证分析结论。 二,实验内容 设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。 三,实验环境 Turbo C 或VC++ 四,实验学时 2学时,必做实验 五,数据结构与算法 #include #include #define TRUE 1 #define FALSE 0 typedef struct Node { double x; double y; }Node; //坐标 typedef struct List { Node* data; //点 int count; //点的个数 }List; typedef struct CloseNode { Node a; Node b; //计算距离的两个点 double space; //距离平方 }CloseNode;

int n; //点的数目 //输入各点到List中 void create(List &L) { cout<<"请输入平面上点的数目:\n"; cin>>n; L.count=n; L.data = new Node[L.count]; //动态空间分配 cout<<"输入各点坐标 :x_y):"<>L.data[i].x>>L.data[i].y; } //求距离的平方 double square(Node a,Node b) { return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y)); } //蛮力法 void BruteForce(const List &L,CloseNode &cnode,int begin,int end) { for(int i=begin;i<=end;++i) { for(int j=i+1;j<=end;++j) { double space=square(L.data[i],L.data[j]); if(space

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

函数的递归调用与分治策略 递归方法是算法和程序设计中的一种重要技术。递归方法即通过函数或过程调用自身将问题转化为本质相同但规模较小的子问题。递归方法具有易于描述和理解、证明简单等优点,在动态规划、贪心算法、回溯法等诸多算法中都有着极为广泛的应用,是许多复杂算法的基础。递归方法中所使用的“分而治之”的策略也称分治策略。 递归方法的构造 构造递归方法的关键在于建立递归关系。这里的递归关系可以是递归描述的,也可以是递推描述的。下面由一个求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.掌握分治算法的基本思想(分-治-合)、技巧和效率分析方法。 2.熟练掌握用递归设计分治算法的基本步骤(基准与递归方程)。 3.学会利用分治算法解决实际问题。 二、问题描述 金块问题 老板有一袋金块(共n块,n是2的幂(n≥2)),最优秀的雇员得到其中最重的一块,最差的雇员得到其中最轻的一块。假设有一台比较重量的仪器,希望用最少的比较次数找出最重和最轻的金块。并对自己的程序进行复杂性分析。 3、问题分析 一般思路:假设袋中有n 个金块。可以用函数M a x,通过n-1次比较找到最重的金块。找到最重的金块后,可以从余下的n-1个金块中用类似法通过n-2次比较找出最轻的金块。这样,比较的总次数为2n-3。 分治法: 如果集合中只有1个元素,则它既是最大值也是最小值; 如果有2个元素,则一次maxnum(i,j) 一次minnum(i,j)就可以得到最大值和最小值; 如果把集合分成两个子集合,递归的应用这个算法分别求出两

个子集合的最大值和最小值,最后让子集合1的最大值跟子集合2的最大值比较得到整个集合的最大值;让子集合1的最小值跟子集合2的最小值比较得到整个集合的最小值。 四、程序设计 对金块问题的程序设计如下: (1)核心算法分析 double Search_Max(double g[],int left,int right)与double Search_Min(double g[],int left,int right)函数分别是求最大重量与最小重量金块的被调用函数,函数体中 当left==right时,只有一个重量,最小和最大重量相等,分别直接返回返回g[left],g[right]。 当right-left==1时,有两个重量,分别调用一次min(g1,g2)和max (g1,g2)函数就可得出最小与最大重量,分别返回。 当right-left>1时,mid=(left+right)/2取中点,将数据群分为两半,分别递归调用,最后将得到的两个数据群的最值运用min()或max()函数得到最小最大重量。 (2)函数调用及主函数设计 Int main()中,首先输入要输入的数据个数n,运用for循环将数据输入到gold[0~n]数组中,然后分别调用Search_Max(gold,0,n-1)和Search_Min(gold,0,n-1)函数输出最小最大重量;

递归与分治算法设计

算法设计与分析实验报 告

2) 3) 4) 2.假币识别问题的程序: package com.t3; //假币问题 import java.util.Scanner; public class Main { static final int MAXNUM = 20; private static int FalseCoin(int[] coin, int low, int high) { int sum1 = 0, sum2 = 0, sum3 = 0; int re = 0; if ( low+1 == high ) { if ( coin[low] < coin[high] ) { re = low+1; return re; }else { re = high+1; return re; } } if ( (high-low+1)%2 == 0 ) {//如果n是偶数 //前半段 for ( int i = low; i <= low+(high-low)/2; i++ ) { sum1 = sum1 + coin[i]; } //后半段 for ( int i = low+(high-low)/2+1; i <= high; i++ ) {

int n = in.nextInt(); System.out.println("请输入所有硬币质量: "); for ( int i = 0; i < n; i++ ) { coin[i] = in.nextInt(); } int p = FalseCoin(coin, 0, n-1); System.out.println("假币在" + p + "个位置"); } } 实例: 1) 2) 实验心得体会: 实验成绩:指导教师:年月日

函数递归调用讲解

函数递归调用讲解 一、函数调用与返回流程: 在一个函数中调用另一个函数时,程序控制即转入到被调用的函数中,在函数代码执行完成后,返回到主函数中的调用处继续执行主函数中的后续代码。见以下的程序: #include "Stdio.h" #include "Conio.h" int sub(int x) { int z; ...... return z; } int main(void) { ....... y=sub(x); ....... getch(); return 0; } 当主函数执行到y=sub(x)时,将变量x的值作为参数传递到函数sub的形式参数x中,程序控制转入到sub函数中;执行函数sub中的代码,遇到return z时,将变量z的值作为函数的结果值返回,程序控制转回到主函数main中继续执行其后的代码。如下图所示: 如果在函数sub中又调用了其他的函数如fun,则形成了函数的嵌套调用。

从上图中可以看到,函数调用是逐级调用、逐级返回的。即从函数fun中只能返回到函数sub中,而不能直接返回到函数main中。 二、递归调用 如果一个函数调用了这个函数自己,则形成递归调用。递归调用是一种特殊的嵌套调用,在调用与返回的流程上与函数嵌套调用没有区别。但由于函数调用自己,因此在理解上有一定的难度。 例:使用函数递归调用计算n!。阶乘计算的递推公式为: 0!=1,1!=1……n!=n*(n-1)! #include "Stdio.h" #include "Conio.h" int fun(int n) { int f; if(n==1||n==0) f=1; else f=n*fun(n-1); return f; } int main(void) { int x,p; scanf("%d",&x); p=fun(x); printf("%d",p); getch(); return 0; } 下图示出了当输入x=3时,函数调用与返回的情形。注意:在每一次调用函数fun时,变量n的值都是不同的。

相关文档
最新文档