递归程序设计方法及实例

来源:互联网 发布:android mac 编辑:程序博客网 时间:2024/05/16 16:16

                                                                                                递归程序设计方法及实例

    实例1:一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?

//卖鸭子#include<stdio.h>int num(int sum,int day);int main(){int s=num(2,8);                         //第七天还剩余鸭子2只printf("鸭子总数为%d只\n\n",s);for(int day=1;day<=7;day++)             //输出每天卖出的鸭子数{printf("第%d天卖出%d只\n",day,s/2+1);s=s/2-1;}return 0;}int num(int sum,int day){if(day==1)return sum;elsereturn num((sum+1)*2,day-1);        //递归计算鸭子数return 0;}

   实例2:角谷定理。输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以31。经过如此有限次运算后,总可以得到自然数值1。求经过多少次可得到自然数1

如:输入22

输出 22 11 34 17 52 26 13 40 20 10 5 16 8 4 1

//角谷定理#include<stdio.h>int step;int calculate(int a);int main(){int a;                       //输入的自然数aprintf("请输入一个自然数:");scanf("%d",&a);  calculate(a);return 0;}int calculate(int a){printf("%6d",a);if(a==1)printf("\nStep is %d\n",step+1);        else{ if(a%2==0)           //输入的自然数为偶数{a=a/2;step++;          //每计算一次,step加1calculate(a);    //递归调用}else if(a%2!=0)      //输入的自然数为奇数{a=a*3+1;step++;calculate(a);}}return 0;}
           实例三:电话号码对应的字符组合:在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。现在输入一个3到11位长的电话号码,请打印出这个电话号码所对应的字符的所有可能组合和组合数。

//电话号码对应字符组合//假设此程序中,0和1对应的英文字母分别为'*','#'//做出此假设的原因是因为0和1没有对应的英文字母#include<stdio.h>#define M 12#define N 30int a[M];               //a[M]存储电话号码每位上的数字char b[28]={'*','#','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; //b[M]存储每个数字对应的不同的英文字母char c[10][10] = {      //用字符数组存储每个数字对应的不同英文字母    '*', '#', "ABC", "DEF",    "GHI", "JKL", "MNO",    "PQRS", "TUV", "WXYZ"};int i,n;int GroupNum(int x); int main(){printf("请输入电话号码的总位数:");scanf("%d",&n);for(i=0;i<n;i++){printf("请输入电话号码的第%d位:",i+1);scanf("%d",&a[i]);}i=0;printf("此电话号码对应的字符串组合共有%d组\n",GroupNum(1));return 0;}int GroupNum(int x)       //求总共组合数{if(i==n)return x;else{if(a[i]==0 || a[i]==1)       {x=1*x;i++;GroupNum(x);  //递归调用  }else if(a[i]==2 || a[i]==3 || a[i]==4 || a[i]==5 || a[i]==6 || a[i]==8 )  {x=3*x;i++;GroupNum(x);}else{x=4*x;i++;GroupNum(x);}}}
         实例4:日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个桔子分给六个儿子。分完 后父亲说:“老大将分给你的桔子的1/8给老二;老二拿到后连同原先的桔子分1/7给老三;老三拿到后连同原先的桔子分1/6给老四;老四拿到后连同原先的桔子分1/5给老五;老五拿到后连同原先的桔子分1/4给老六;老六拿到后连同原先的桔子分1/3给老大”。结果大家手中的桔子正好一样多。问六兄弟原来手中各有多少桔子?

//分桔子问题#include<stdio.h>// oldUNum为每个人原有桔子数,getNum为得到的桔子数,n为第几个人int orangeNum(int oldNum,int getNum,int n);int main(){//老大原有240个桔子,得到210个orangeNum(240,210,1);return 0;}int orangeNum(int oldNum,int getNum, int n){int nextGetNum,nextOldNum,m;    if(n > 6)      //递归出口return 0;        else{printf("     第%d个人原有桔子%d\n",n,oldNum);  //输出原先橘子数                if(n == 1)                                     //计算分给下一个人的橘子数nextGetNum = oldNum/(9 - n);                else             nextGetNum = (oldNum+getNum)/(9-n);        nextOldNum = 2520/6* (8-n)/(7-n) - nextGetNum;  //下一个人原来的橘子        m = n+1;        orangeNum(nextOldNum,nextGetNum,m);        }return 0;}
                                                                     递归程序设计方法总结

                                                                                                                                                 ————常见递归问题的分析与设计

       1.卖鸭子问题:这是常见的递归函数问题,求得一个递归函数公式即可。设计函数int num( int sum,int day);其中sum参数返回鸭子的数量,day参数返回第几天。编写递归程序的关键为确定递归出口和递归体。本题递归出口为当day==1时,return sum;递归体为当day!=1时,return num((sum+1)*2,day-1);同时在主函数中输出每天所卖的鸭子数目。

       2.角谷定理:本题的设计思路比较简单,仍然为一个递归函数问题。按照题意,输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以31。经过如此有限次运算后,总可以得到自然数值1。得到递归结束出口为a==1;return总步数。递归体为当a==偶数时,自身除以二,并累加步数,返回calculate函数。当a为奇数时,自身乘三加一,并累加步数,返回calculate.

      3.电话号码对应的字符组合:首先清楚2,3,4,5,6,8六个数字对应三个英文不同的字母,8,9三个数字对应4个不同的英文字母。由于数字10并没有对应的英文字母,所以假设01分别对应’*’,’#’,这种假设并不影响最后递归算法的设计。还可以增强程序的健壮性。

      计算组合数:需要统计电话号码有几个数字,且每个数字对应几个英文字母。把每个数字对应的英文字母个数乘起来即为组合数。

      计算具体的组合:需要统计具体哪几个数字,每个数字具体对应的英文字母是什么。逐一进行组合即可。

      4.中村义作教授分桔子问题:这是一个环状互相关联的问题,想到应该使用递归来求解。首先应该分析得到已知和隐含条件。

最后桔子数目相等,则每人为420个。同时老大的身份最特殊,其余的人都是先得到再给出桔子,而老大是先给出后得到,并且最后为420个,由老六分给他210个桔子,则老大原来有240个桔子,老大原先有240个桔子,分出210个桔子,问题的突破口就找到了。设计函数orangeNum(oldNum,getNum,n);三个参数分别为原有桔子数,得到桔子数,和第几个人。将240,210,1三个参数传入后,就开始了递归函数的调用,当n>6时,递归调用结束。

       递归问题总结:递归是程序直接或者间接调用自身的过程,递归模型由递归出口和递归体两部分组成,分析问题时主要要抽象出递归出口和递归体。递归问题一般分为两大类:一类是比较简单的数学上的递归函数,要求算得一个函数值,只需要将递归函数翻译出来即可。第二类为问题为一些实际的问题,没有统一的规律可循,解决问题的关键为充分的理解问题,发现问题中的已知和隐含条件。根据逻辑关系分析此问题为什么为一个递归问题,并由此得到递归出口和递归递归体,从而使问题得到解决。这类问题都比较复杂,需要进行大量的练习才能建立这种思维方式。







 
0 0
原创粉丝点击