C语言中递归函数的设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

下面我们再来看一个非数值问题的递归算法 例2汉诺塔(Hanoit)问题 这是一个著名的问题,相传在很久很久以前, 在中东地区的一个寺庙里,几个和尚整天不停地 移动着盘子,日复一日,年复一年,移盘不止, 移动盘子的规则是这样的:事先固定三根针,假 设分别为A针,B针,C针,A针上套有64个中间 带孔的盘子,盘子大小不等,大的在下,小的在 上,要求把这64个盘子从A针移到C针,在移动过 程中可以借助于B针,每次只允许移动一个盘子, 且移动过程中的每一步都必须保证在三根针上都 是大盘在下,小盘在上.据说当所有64个盘子全 部移完的那一天就是世界的末日,故汉诺塔问题 又被称为"世界末式的问题,如求非负整数N 的阶乘,求斐波那契数列的第n项,求两个整 数的最大公约数等. 2,非数值问题 其本身难以用数学公式表达的问题,如著名的 汉诺塔问题,八皇后问题.
三,递归函数设计的一般步骤
编写递归程序有两个要点:一是要找到正确的 一是要找到正确的 递归算法,这是编写递归程序的基础; 递归算法,这是编写递归程序的基础;二是要 确定递归算法的结束条件, 确定递归算法的结束条件,这是决定递归程序 能否正常结束的关键. 能否正常结束的关键.
不难计算,对于n个盘子需要移动2n -1次,把64个 盘子都移动完毕约需1.8X1019次,假设每秒移动 一次,约需一万亿年,若用现代电子计算机计算, 设一微秒可计算(并不输出)一次移动,也几乎需 要一百万年.目前,由于计算机运算速度的限制, 我们仅能找出问题的解决方法并解决较小n值的汉 诺塔问题. 讨论:汉诺塔问题属于非数值问题,难以用 数学公式表达其算法,可以从分析问题本身的规 律入手. 第一步,问题化简,设A针上只有一个盘子, 即n=1,则只需将1号盘从A针移到C针. 第二步,问题分解,对于有n(n>1)个盘子 的汉诺塔,可分为三个步骤求解:
#include<stdio.h> void main() { void movedisk(int n,char fromneedle,char tempneedle,char toneedle); int n; printf ("Pleases input the number of diskes:"); scanf("%d",&n); printf ("The step moving diskes is:\n"); movedisk (n,'A','B','C'); } void movedisk(int n,char fromneedle,char tempneedle,char toneedle) { if (n==1) printf ("%c %c\n",fromneedle,toneedle ); else { movedisk(n-1,fromneedle,toneedle,tempneedle ); printf ("%c %c\n",fromneedle,toneedle ); movedisk (n-1,tempneedle,fromneedle,toneedle ); } }
从前有座山,山上有个庙,庙里有个老和尚 和3岁的小和尚,老和尚给小和尚讲故事,讲的是: 从前有座山,山上有个庙,庙里有个老和尚和2岁 的小和尚,老和尚给小和尚讲故事,讲得是:从 前有座山,山上有个庙,庙里有个老和尚和1岁的 小和尚. 这里的递归结束条件即小和尚的年龄,因为 没有0岁的小和尚,所以讲到"庙里有个老和尚和 l岁的小和尚"时,故事结束.每次递归都使小和 尚的年龄减少一岁,所以总有终止递归的时候, 不会产生无限递归.
第一步,将问题进行化简,将问题的规模缩到 第一步 最小,分析问题在最简单情况下的求解方法, 这时的算法应当是最简单的非递归算法. 第二步,将问题分解为若干个小问题,其中至 第二步 少有一个小问题具有与原问题相同的性质,只 是在规模上比原问题有所缩小,将分解后的每 个小问题作为一个整体,描述用这些较小的问 题解决原来较大问题的算法. 由第二步得到的算法就是一个解决原问题的递 归算法,第一步将问题的规模缩到最小时的条 件就是该递归算法的结束条件.
C语言中递归函数的设计 语言中递归函数的设计
主讲人 熊立伟 (武汉大学 遥感信息工程学院)
1,教学目标 使学生学会使用和设计递归函数去解决较复杂 的问题 2,教学重点 递归函数的定义,递归问题的分类,递归函数 设计的一般步骤 3,教学难点 理解递归函数的内涵,确定递归结束条件 4,教学方法 讲故事激发学生兴趣,巧解概念,典型例题分 析
五,总结
递归是一个十分有用的方法.当一个问题 蕴含了递归关系且结构比较复杂时,采用递归 调用的程序设计技巧可以使程序变得简洁,增 加了程序的可读性,递归调用能使代码紧凑, 并能够很容易地解决一些用非递归法很难解决 的问题. 当然,递归算法也有它的缺点,递归程序 通常要花费较多的机器时间和占用较多的存储 空间,另外也不是每个问题都适合用递归方法 求解.
三,典型例题分析
首先来看一个数值问题的递归算法
例1用辗转相除法求整数m与n的最大公约数. 讨论:此问题属于数值问题,求m与n的最大 公约数等价于求n与(m%n)的最大公约数,这时可 以把n当作新的m,(m%n)当作新的n,问题变成了 求新的m与新的n的最大公约数,它又等价于求新 的n与(m %n)的最大公约数……如此继续,直到 新的n=0时,所求最大公约数就是新的m,这就是 用辗转相除法求m与n的最大公约数的过程. 因此,有如下递归算法: 1.求r=m%n 2.若r=0,则n为所求,输出n,结束 3.若r!=0,则令m=n,n=r 4.转向步骤1 按照上述算法可编写出如下C语言程序:
movedisk(int n,char fromneedle,char tempneedle,char toneedle) { if (n==1) 将n号盘子从one针移到three针; esle 1. movedisk(n-1 , fromneedle , toneedle , tempneedle) 2.将n号盘子从fromneedle针移到toneedle针; 3. movedisk(n-1, tempneedle, fromneedle, toneedle) } 按照上述算法可编写出如下C语言程序:
1.将A针上n-1个盘子借助于C针移到B针 2.把A针上剩下的一个盘子移到C针 3.将B针上n-1个盘子借助于A针移到C针 显然,上述1,3两步具有与原问题相同的性质, 只是在问题的规模上比原问题有所缩小,可用递 归实现. 整理上述分析结果,把第一步作为递归结束 条件,将第二步分析得到的算法作为递归算法, 可以写出如下完整的递归算法描述: 定义一个函数movedisk (int n,char fromneedle ,char tempneedle , char toneedle ), 该函数的功能是将fromneedle针上的n个盘子借助 于tempneedle针移动到toneedlee针,这样移动n 个盘子的递归算法描述如下:

有这么一个古老的故事:从前有座山,山上 有个庙,庙里有个老和尚和小和尚,老和尚给小 和尚讲故事,讲的是:从前有座山,山上有个庙, 庙里有个老和尚和小和尚,老和尚给小和尚讲故 事,讲的是…… 这是一个典型的"递归"故事,可以无限次 递归下去.当大人们肚中无故事而又要哄小孩时, 常常讲这个故事. 我们可把这个故事比喻成递归调用,但在C 语言程序设计中,程序不可无限地递归下去,必 须有递归结束条件,而且每次递归都应该向结束 条件迈进,直到满足结束条件而停止递归调用. 为此,可将上述"递归"故事修改如下:
前面我们把递归问题分为两大类:数值问题和非 数值问题.这两类问题具有不同的性质,所以解 决问题的方法也不同. 对于数值问题,由于可以表达为数学公式, 对于数值问题 所以可以从数学公式入手推导出问题的递归定义, 然后确定问题的边界条件,从而确定递归的算法 和递归结束条件. 对于非数值问题,其本身难以用数学公式表 对于非数值问题 达.求解非数值问题的一般方法是要设计一种算 法,找到解决问题的一系列操作步骤.如果能够 找到解决问题的一系列递归操作步骤,同样可以 用递归的方法解决这些非数值问题,寻找非数值 问题的递归算法可以从分析问题本身的规律入手, 可以按照下列步骤进行分析:
#include<stdio.h> void main() { int gcd(int m,int n); int m,n,g; printf("请输入整数m,n:"); scanf("%d%d",&m,&n); printf("\n"); g=gcd(m,n); printf("%d和%d的最大公约数是:%d\n",m,n,g); } int gcd(int m,int n) { int g; if(n==0) g=m; else g=gcd(n,m%n); return g; }
新课导入:C程序结构是函数模块结构,C程序是 由一个或多个函数构成的,是函数的集合.函 数具有相对独立的特定功能,是程序的基本单 位,因此,在C语言教学中,函数这一章(大部 分教材把函数作为一章)是重点内容,而函数的 递归调用则是这一章的重点之一.下面我们首 先来看递归函数的定义
一,递归的定义
在调用一个函数的过程中调用该函数本身,称 为函数的递归调用.递归调用简称递归.
相关文档
最新文档