(精品)jidao-chap6递归算法设计(1).ppt
《(精品)jidao-chap6递归算法设计(1).ppt》由会员分享,可在线阅读,更多相关《(精品)jidao-chap6递归算法设计(1).ppt(63页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、 第五章第五章 函数函数-递归递归选自:选自:计算机导论与程序设计基础计算机导论与程序设计基础 第第6章以及第章以及第16章的章的16.1C程序设计教程程序设计教程 5.135.151 1.递归的概念递归的概念2.递归过程递归过程3.递归程序设计递归程序设计提纲提纲2 1.递归的概念递归的概念递归算法递归算法在可计算性理论中占有重要地位,它在可计算性理论中占有重要地位,它是算法设计的有力工具,对于拓展编程思路非是算法设计的有力工具,对于拓展编程思路非常有用。就递归算法而言并不涉及高深数学知常有用。就递归算法而言并不涉及高深数学知识,只不过初学者要建立起递归概念不十分容识,只不过初学者要建立起递
2、归概念不十分容易。易。我们先从一个最简单的例子导入。我们先从一个最简单的例子导入。3 1.递归的概念递归的概念例例1:编写一个函数:编写一个函数fac,计算阶乘,计算阶乘n!按过去按过去的迭代算法的迭代算法,该函数可以写成:,该函数可以写成:int fac(int n)int i,p;p=1;for(i=2;i=n;i+)p=p*i;return p;4 现在换一个角度考虑,现在换一个角度考虑,n!不仅是!不仅是123n,还可以定义成:还可以定义成:int f(int n)if(n=0)return 1;else return n*f(n-1);1 当当n0 n!n(n1)!当当n01.递归的
3、概念递归的概念设设 f(n)=n!1 当当n0则则 f(n)nf(n-1)当当n0根据以上数学定义,函数根据以上数学定义,函数f能否写成能否写成左边所示?左边所示?函数能否调用自身?函数能否调用自身?答案是肯定的答案是肯定的!C系统会保系统会保证调用过程的正确性,这证调用过程的正确性,这就是递归!就是递归!5 递归的定义:递归的定义:u 从程序书写来看,在定义一个函数从程序书写来看,在定义一个函数时,若在函数的功能实现部分又出现时,若在函数的功能实现部分又出现对它本身的调用,则称该函数是递归对它本身的调用,则称该函数是递归的或递归定义的。的或递归定义的。u 从函数动态运行来看,当调用一个函从函
4、数动态运行来看,当调用一个函数数A时,在进入函数时,在进入函数A且还没有退出且还没有退出(返回)之前,又再一次由于调用(返回)之前,又再一次由于调用A本身而进入函数本身而进入函数A,则称之为函数,则称之为函数A的的递归调用。递归调用。int f(int n)if(n=0)return 1;else return n*f(n-1);6 递归可以分为直接递归和间接递归两种。递归可以分为直接递归和间接递归两种。直接递归直接递归:函数体里面发生对自己的调用;:函数体里面发生对自己的调用;间接递归间接递归:函数:函数A A调用函数调用函数B B,而函数而函数B B又直接或又直接或间接地调用函数间接地调用
5、函数A A。1.递归的概念递归的概念A()B();B()A();A()A();直直接接递递归归间间接接递递归归7 1.递归的概念递归的概念不用担心函数不用担心函数A内部又调用函数内部又调用函数A,会使得调用无休无,会使得调用无休无止,肯定存在某个条件,当该条件成立的时候,函数止,肯定存在某个条件,当该条件成立的时候,函数A将不会再调用自身。将不会再调用自身。例如,求例如,求n!时,该结束条件是!时,该结束条件是 if(n=0)int f(int n)if(n=0)return 1;else return n*f(n-1);8 1.递归的概念递归的概念2.递归过程递归过程3.递归程序设计递归程序
6、设计提纲提纲9 2.递归过程递归过程求求f(2)的)的 递归调用过程?递归调用过程?#include int f(int);main()int i=2;printf(“%d”,f(i);system(“pause”);int f(int n)/递归函数:求递归函数:求n!if(n=0)return 1;else return n*f(n-1);10 2.递归过程递归过程int f(int n)if(n=0)return 1;else return n*f(n-1);调用调用调用调用11返回返回211 2.递归过程递归过程请思考:请思考:发出发出f(2)调用时,将调用时,将2赋值给形参赋值给形参
7、n。然后发出。然后发出f(1)调用,将调用,将1赋值给形参赋值给形参n。接着发出。接着发出f(0)调用,将调用,将0赋值给形参赋值给形参n。后。后来赋给形参来赋给形参n的值会不会覆盖原来赋给的值会不会覆盖原来赋给n的值(如值的值(如值1覆盖覆盖原来的值原来的值2)?为什么?)?为什么?不会,每一次函数调用会在栈顶分配新的活动记录。不会,每一次函数调用会在栈顶分配新的活动记录。对递归函数的每一次调用结束返回时,为何能回到调用前对递归函数的每一次调用结束返回时,为何能回到调用前的程序运行状态?如的程序运行状态?如f(1)调用结束返回调用结束返回f(2)时,时,n的值为的值为2。函数访问的永远是栈顶
8、的活动记录。当函数访问的永远是栈顶的活动记录。当f(1)调用结束时,调用结束时,位于栈顶的位于栈顶的f(1)的活动记录将出栈,此时位于栈顶的将是的活动记录将出栈,此时位于栈顶的将是f(2)的函数活动记录。的函数活动记录。12 回顾函数调用过程函数调用过程2.递归过程递归过程 被调用函数中被调用函数中的数据的数据 现场信息,用现场信息,用于调用结束能于调用结束能正确返回并执正确返回并执行行13 f(0)返返回值回值1f(1)返返回值回值1f(2)返返回值回值2调用调用f(2)调用调用f(1)调用调用f(0)5.printf(“%d”,f(i);8.int f(int n)9.10.if(n=0)
9、11.return 1;12.else13.return n*f(n-1);14.1.int f(int);2.main()3.4.int i=2;5.printf(“%d”,f(i);6.system(“pause”);7.8.int f(int n)/递归函数:求递归函数:求n!9.10.if(n=0)11.return 1;12.else13.return n*f(n-1);14.14 求求f(6)的递归调用过程的递归调用过程递递推推阶阶段段回回归归阶阶段段返回返回15 2.递归过程递归过程可见,可见,递归算法的执行过程分递归算法的执行过程分递推递推和和回归回归两个阶两个阶段段。当递推时
10、,并没有求值的计算操作,实际的当递推时,并没有求值的计算操作,实际的计算操作是在回归过程实现的。计算操作是在回归过程实现的。递推阶段:递推阶段:递推递推阶段是个不断简化问题的阶段:把对较复阶段是个不断简化问题的阶段:把对较复杂问题(规模为杂问题(规模为n)的求解转化为比原问题)的求解转化为比原问题简单简单一些的问题(规模小于一些的问题(规模小于n)的求解)的求解。例如对。例如对f(6)的求解转化为的求解转化为f(5)的求解,的求解,对对f(5)的求解转化为的求解转化为f(4)的求解的求解直到转化为对直到转化为对f(0)的求解。的求解。当递推到当递推到最简单的不用再简化的问题时最简单的不用再简化
11、的问题时,递推,递推终止。如终止。如f函数中,函数中,n=0的情况。的情况。就象剥一颗圆白菜,从外向里,一层层剥下来,到就象剥一颗圆白菜,从外向里,一层层剥下来,到了菜心,就不再继续剥了。了菜心,就不再继续剥了。16 2.递归过程递归过程回归阶段:回归阶段:在在回归阶段回归阶段,当获得最简单情况的解后,逐,当获得最简单情况的解后,逐级返回,依次得到稍复杂问题的解级返回,依次得到稍复杂问题的解。如在得。如在得到到f(1)的解后,又依次得到的解后,又依次得到f(2)、f(3)直到直到f(6)的值。的值。就像将剥下来的白菜叶又从里往外一叶一叶就像将剥下来的白菜叶又从里往外一叶一叶合起来,直到最外层菜
12、叶。合起来,直到最外层菜叶。17 2.递归过程递归过程思考:递归思考:递归与迭代的比较与迭代的比较(以求阶乘为例以求阶乘为例)。迭代迭代:从已知的初始条件出发,逐次去求所需从已知的初始条件出发,逐次去求所需要的阶乘值,这相当于从要的阶乘值,这相当于从菜心菜心“推到推到”(通(通过循环)最外层的过循环)最外层的菜叶菜叶。f(0)=1f(1)=1*f(0)=1f(2)=2*f(1)=2递归:先从最外层的递归:先从最外层的菜叶菜叶“递推递推”到到菜心菜心(递递归函数调用归函数调用),再从,再从菜心菜心“回归回归”到最外面的到最外面的菜叶菜叶(递归函数返回)。(递归函数返回)。18 2.递归过程递归过
13、程递归递归算法的出发点不放在初始条件上,而放在求解的算法的出发点不放在初始条件上,而放在求解的目标上,是从所求的未知项出发逐次调用本身的求解目标上,是从所求的未知项出发逐次调用本身的求解过程,直到递归的边界(即初始条件)。过程,直到递归的边界(即初始条件)。就求阶乘而言,读者会认为递归算法可能是多余的,就求阶乘而言,读者会认为递归算法可能是多余的,费力而不讨好。费力而不讨好。但许多实际问题不可能或不容易找到但许多实际问题不可能或不容易找到显而易见的迭代关系,这时递归算法就表现出了明显显而易见的迭代关系,这时递归算法就表现出了明显的优越性。的优越性。下面我们将会看到,下面我们将会看到,递归算法比
14、较符合人的思维方式,递归算法比较符合人的思维方式,逻辑性强,可将问题描述得简单扼要,具有良好的可逻辑性强,可将问题描述得简单扼要,具有良好的可读性,易于理解,读性,易于理解,许多看来相当复杂,或难以下手的许多看来相当复杂,或难以下手的问题,如果能够使用递归算法就会使问题变得易于处问题,如果能够使用递归算法就会使问题变得易于处理。理。19 1.递归的概念递归的概念2.递归过程递归过程3.递归程序设计递归程序设计提纲提纲20 什么样的问题可以用递归解决?什么样的问题可以用递归解决?如果解决问题的方法是把该问题分解成小的子如果解决问题的方法是把该问题分解成小的子问题,并且这些小的子问题可以用同样的算
15、法问题,并且这些小的子问题可以用同样的算法解决,这样不断分解,直到子问题比较简单、解决,这样不断分解,直到子问题比较简单、可以直接解决时分解过程即终止,那么就可以可以直接解决时分解过程即终止,那么就可以用递归。用递归。递归的思想就是将一个问题先转化为与原问题递归的思想就是将一个问题先转化为与原问题性质相同、但规模小一级的子问题,然后再重性质相同、但规模小一级的子问题,然后再重复这样的转化,直到问题的规模减小到我们很复这样的转化,直到问题的规模减小到我们很容易解决为止。容易解决为止。3.递归程序设计递归程序设计21 u一般来说,递归需要有边界条件、递归前进段和递一般来说,递归需要有边界条件、递归
16、前进段和递归返回段。当边界条件不满足时,递归前进;当边界归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归逐级返回。条件满足时,递归逐级返回。u如何设计递归算法如何设计递归算法:1)对所求解的问题、要计算的函数书写递归)对所求解的问题、要计算的函数书写递归 定义;定义;注意一定要有终止条件和对应的操作。注意一定要有终止条件和对应的操作。2)正确地设计递归函数的参数。)正确地设计递归函数的参数。注意:递归算法最外层肯定采用的是选择结构!为注意:递归算法最外层肯定采用的是选择结构!为什么?什么?3.递归程序设计递归程序设计22 例例2.求浮点数求浮点数x的的n次幂次幂(n0)。函数。函
17、数 递归定义递归定义:1 当当n0 x*当当n0float power(float x,int n)if(n=0)return 1;else return x*power(x,n-1);递归程序设计举例递归程序设计举例23 递归程序设计举例递归程序设计举例例例3.设计递归函数求任意正整数的位数。设计递归函数求任意正整数的位数。num=1234int length(int num)if(num/10=0)return 1;else return length(num/10)+1;int length(int num)int len;len=0;if(num/10=0)len=1;else/从最低
18、位开始,依次从从最低位开始,依次从n中砍掉各位中砍掉各位while(num 0)num=num/10;/去掉最低位去掉最低位 len+;/*分解出一位数字,长度加分解出一位数字,长度加1*/return len;1 if num/10=length(num)=length(num/10)+1 if num/100024 递归程序设计举例递归程序设计举例调用调用调用调用返回值返回值325 递归程序设计举例递归程序设计举例例例4.求任意正整数的逆置数。求任意正整数的逆置数。num=1234递归思路递归思路1 1:将除最高位之外的数先逆置。:将除最高位之外的数先逆置。例如:例如:reverse(12
19、34)=1reverse(234)10思路思路1递归定义:递归定义:reverse(num)=num if num长度为长度为1 highBit+reverse(restNum)10 if num长度大于长度大于1其中:其中:highBit=num/power(10,len-1);restNum=num%power(10,len-1);len=num的长度;的长度;递归函数参数设计考虑:递归函数参数设计考虑:len作为递归函数的参数传入作为递归函数的参数传入26 递归设计思路递归设计思路1:num=1234 reverse(1234,4)1+reverse(234,3)*10 reverse(
20、234,3)=2+reverse(34,2)*10 reverse(34,2)=3+reverse(4,1)*10 reverse(4,1)=4返回返回4返回返回3+4*10=43返回返回2+43*10=432返回返回1+432*10=4321递归程序设计举例递归程序设计举例27 递归程序设计举例递归程序设计举例int reverse(int num,int len)int restNum,highBit;if(len=1)/如果如果num是个位数则递归结束是个位数则递归结束 return num;else highBit=num/power(10,len-1);/得到最高位得到最高位 res
21、tNum=num%power(10,len-1);/得到剩余位得到剩余位 /递归调用,并形成逆置数递归调用,并形成逆置数 return highBit+reverse(restNum,len-1)*10;num=1234自定义自定义power函数:函数:int power(int x,int y)28 递归程序设计举例递归程序设计举例例例4.求任意正整数的逆置数。求任意正整数的逆置数。num=1234递归思路递归思路2 2:将除最低位之外的数先逆置。:将除最低位之外的数先逆置。例如:例如:reverse(1234)=4*1000+reverse(123)递归定义递归定义1:reverse(nu
22、m)=num if num长度为长度为1 lowBit*power(10,len-1)+reverse(restNum)if num长度大于长度大于1其中:其中:lowBit=num%10;restNum=num/10;len=num的长度;的长度;29 递归程序设计举例递归程序设计举例递归设计思路递归设计思路2:num=1234 reverse(1234,4)4*1000+reverse(123,3)reverse(123,3)=3*100+reverse(12,2)reverse(12,2)=2*10+reverse(1,1)reverse(1)=1 返回返回1返回返回2*10+1=21返
23、回返回3*100+21=321返回返回4*1000+321=432130 递归程序设计举例递归程序设计举例int reverse(int num,int len)int restNum;int lowBit;if(len=1)/余数为余数为0,作为递归的结束条件,作为递归的结束条件 return num;else lowBit=num%10;/保留最低位保留最低位 restNum=num/10;/得到除去最低位后的余数得到除去最低位后的余数 /递归调用,并形成逆置数递归调用,并形成逆置数 return lowBit*power(10,len-1)+reverse(restNum,len-1);
24、num=123431 递归程序设计举例递归程序设计举例例例5.5.输入输入n n个整数,求最大数。个整数,求最大数。15 30 34 1015 30 34 10 89 89 设函数设函数findMax(nfindMax(n)为读取为读取n n个数,求最大值个数,求最大值 函数函数Maximum(x,yMaximum(x,y)为求两个数为求两个数x x和和y y的最大值的最大值则则findMax(nfindMax(n)递归定义递归定义1 1:findMax(1)=NfindMax(1)=N1 1 当当 n n值为值为1 1findMax(nfindMax(n)=Maximum(findMax(n
25、-1),N)=Maximum(findMax(n-1),Nn n)当当n1n1求前求前n(n1)个数的最大值,分解为个数的最大值,分解为3步:步:第第1步:读取前步:读取前n-1个数,求出最大值个数,求出最大值max;第第2步:读取第步:读取第n个数个数num;第第3步:返回步:返回num和和max之间的最大值之间的最大值32 递归程序设计举例递归程序设计举例/读取读取n n个数,求最大值个数,求最大值int findMax(int n)int max;/记录前记录前n-1个数中的最大值个数中的最大值 int num;/读取的第读取的第n个值个值 if(n=1)/求前求前1个数中的最大值个数中
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 精品 jidao chap6 递归 算法 设计
限制150内