递归算法实现

递归算法

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

题目分析:

递归终止的条件是到第7个村庄时递归停止

算法构造

定义递归函数f(n),  当 n=8,剩余2只鸭子,;当 0<n<8,总共赶num =(f(n+1)+1)*2只鸭子,卖出num/2+1只鸭子

程序代码

//题目:递归算法解决卖鸭子问题

//作者 :软工1508010206 白瑜

//时间 : 2017/05/20

#include <stdio.h> int f(int n) { int num; if(n==8)//第7个村子过后,也就是到第八个村子时还有2只鸭子 { return 2; } else { num =(f(n+1)+1)*2; //递归调用 printf("第%d个村子卖鸭子%d只\n",n,num/2+1); } return num; } int main() { int num = f(1); printf("总共赶鸭子%d个\n",num); return 0; }

 

运行结果截屏:

 

《递归算法实现》

 

 

2、角谷定理。输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。经过如此有限次运算后,总可以得到自然数值1。求经过多少次可得到自然数1
题目分析

 递归的终止条件是最后值为1;先对输入的数n 进行判断,若 n = 1,则输出1;若输入的数为偶数, 则把它除以2;若为奇数则乘3加1;直到n = 1为止;

算法构造:

 n=1 时, 输出1;若n%2==0(n为偶数)时,n = n/2;若n%2==1(n为奇数)时,n = 3*n+1

程序代码:

//题目:递归算法之角谷定理

//作者 :软工1508010206 白瑜

//时间 : 2017/05/20

#include<stdio.h> int jg(int n,int step) //定义递归函数,参数为数字和步骤数 { if(n!=1) { if(n%2 == 0) { printf("%d ", n); n = n / 2; } else if (n % 2 == 1) { printf("%d ", n); n = 3 * n + 1; } return jg(n, step + 1); } else { printf("%d ", n); step++; } printf("\nSTEP=%d\n",step);//输出步骤数 } //主函数 int main() { int s=0; int num; printf("请输入一个数:"); scanf("%d",&num);//输入数字 jg(num,s); return 0; }

 

运行结果截屏:

 

《递归算法实现》

3.电话号码对应的字符组合:在电话或者手机上,一个数字如2对应着字母ABC,7对应着PQRS。那么数字串27所对应的字符的可能组合就有3*4=12种(如AP,BR等)。现在输入一个3到11位长的电话号码,请打印出这个电话号码所对应的字符的所有可能组合和组合数。 

 题目分析

在这里,递归出口是,当输入的是一个数字时,返回这个数字所有可能性的组合,递归体是当输入一串数字,每个数字代表不同的字符串,返回最后一个数字跟前面已产生的字符串进行组合 

 算法构造

首先建一个数组,用来存放每个数字代表的字符串组合,然后再建一个数组,用来存放每个字符串的长度

程序代码:

//题目:递归算法解决电话号码对应的字符组合问题

//作者 :软工1508010206 白瑜

//时间 : 2017/05/20

#include<iostream> using namespace std; char* letter[10]={"","","ABC","DEF","GHI","JKL","MNO","PQRS","TUV","WXYZ"}; int num[10]={0,0,3,3,3,3,3,4,3,4}; char input[15]; char output[15]; void SL(int t,int length) { if(t == length) { cout<<output<<endl; } for(int i=0; i<num[input[t]]; i++) { output[t] = letter[input[t]][i]; SL(t+1,length); } } int main() { int length; printf("输入一个3到11位长的电话号码:"); scanf("%s",input); printf("该电话号码所对应字符的所有可能的组合是:\n"); length = strlen(input); int total = 1; for(int i=0; i<length; i++) { input[i] -= '0'; total *= num[input[i]]; } SL(0,length); cout<<"组合数:"<<total<<endl; return 0; }

 

运行结果截屏:

 

《递归算法实现》

 

《递归算法实现》

 

4.日本著名数学游戏专家中村义作教授提出这样一个问题:父亲将2520个橘子分给六个儿子。分完后父亲说:“老大将分给你的橘子1/8给老二;老二拿后连同原先的橘子1/7给老三;老三拿到后连同原先的橘子1/6给老四;老四拿到后连同原先的橘子1/5给老五;老五拿到后连同原先的橘子1/4给六;老六拿到后连同原先的橘子1/3给老大”。结果大家手中的橘子正好一样多。问六兄弟原来手中各有多少子?
题目分析:

每个儿子拿到的橘子数目分为原有的和现有的,除了老大,其他的儿子原有的+别人给的-给别人的=现有的=平均数,所以,可以得出原有的=现有的+给别人的-别人给的。 

算法构造:

拿二儿子作说明:老二拿到后连同原先的橘子1/7给老三。(原有的+拿到的)*6/7=ave,所以give=(原有的+拿到的)*1/7=ave*6/7*1/7=give=ave/(8-i-1)(此时i为1),所以每个儿子现有的和原有的关系为: a[i]=a[i]+(a[i]/(8-i-1))-(a[i-1]/(8-(i-1)-1)) 

程序代码:

//题目:递归算法解决分橘子问题

//作者 :软工1508010206 白瑜

//时间 : 2017/05/20

#include<iostream> using namespace std; int main() { int a[6];//存放六个儿子原先手中的橘子数目 int left = 0;//存放下一个儿子得到的橘子数目 int ave = 420; int i; for(i=0;i<6;i++) { if(i==0) { a[i]=(ave-ave/2)*(8-i)/(8-i-1);//第一个儿子的数目, left=a[i]-ave/2; } else { a[i]=ave*(8-i)/(8-i-1)-left;//由left求第i+1个儿子的橘子数目 left=ave/(8-i-1);//第i+1个儿子得到的橘子数目 } } for(i=0;i<6;i++) { cout<<"第"<<i+1<<"个儿子原先手中的橘子数目数为"<<a[i]<<endl;//输出每个儿子原先手中的橘子数目 } return 0; } 

 

运行结果截屏:

 

《递归算法实现》

5.经验归纳

     递归是一种程序设计方法,更恰当的说是一技巧。既然是技巧就会有一些问题,那就是当用得合适时,会有事半功倍的效果,但大多数情况下这种技巧是不适合的。递归程序相比于一般的迭代程序会有更多的程序开销,所以在使用递归前要衡量好简化代码和增加开销之间的关系。

      经过这几个递归例题,我认为要写好一个递归算法,主要把握以下几点:首先要从题目中提取出重复的逻辑,这个逻辑需要一个框架保证其可以递归执行,其次就是控制逻辑边界,保证程序在正确的框架下运行,最后就是合适的退出递归,递归的退出往往和逻辑边界相辅相成,掌握了以上几点,可以让我们在递归算法中少走很多弯路,从而使得程序更加简单方便。

 

    原文作者:递归算法
    原文地址: https://blog.csdn.net/qq_37835374/article/details/72598189
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞