一、题目分析
用递归方法设计下列各题,并给出每道题目的递归出口(递归结束的条件)和递归表达式。同时考虑题目可否设计为非递归方法,如果可以,设计出非递归的算法。
1.一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只。这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?
2.角谷定理。输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。经过如此有限次运算后,总可以得到自然数值1。求经过多少次可得到自然数1。
如:输入22
输出 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
STEP=16
二、算法构造
(1)1.递归构造:
递归出口:num(2,8)
递归体:num((sum+1)2,day-1)
2.非递归构造:
由Left-(left/2+1)=num得left=2(num+1) num=left/2-1
(2)1. 递归构造
递归出口 a=1
递归体
num(a)=1 a=1
num(a)=num(a/2) a%2=0
num(a)=num(a*3+1) a%2!=0
2.非递归构造
用while循环,若是偶数,进行除2,若是奇数,进行乘3加1
三、算法实现
1.卖鸭子:
递归:
int num(int sum,int day)
{
if (day==1)
return sum;
else
return num((sum+1)*2,day-1);
}
非递归:
int main()
{
int num=2;
int sale;
int left;
for(int i=0;i<7;i++)
{
left=2*(num+1);
sale=left/2+1;
num=left;
printf("第%d个村子卖出%d只鸭子\n",7-i,sale);
}
printf("一共有%d只鸭子\n",left);
}
2.角谷定理:
递归:
int num(int a)
{
step++;
if(a==1)
{
return step;
}
else{
if(a%2==0)
{
a=a/2;
printf("%d ",a);
}
else{
a=a*3+1;
printf("%d ",a);
}
return num(a);
}
}
非递归:
int main()
{ int num;
printf("请输入一个自然数:");
scanf("%d",&num);
int step=1;
while(num!=1){
if((num%2)==0){
num=num/2;
}
else{
num=num*3+1;
}
printf("%d ",num);
step++;
}
printf("\nstep=%d\n",step);
}
四、调试、测试及运行结果
1.卖鸭子
递归测试:
非递归测试:
2.角谷定理
将step定义为局部变量,出现错误,无论输入多少,step始终都是1。
将step定义为全局变量之后,运行正确。
五、经验归纳
用递归来处理一些题目是非常简单的,虽然电脑实际运行比较复杂,但是编程的时候语句非常少。在处理递归问题之前一定要先理清思路,思路很重要,如果在思路非常混乱的情况下做题,不光是递归题目,一般的题目也会bug频出,如果递归题目搞不懂的话,可以先考虑循环(while,for),先搞懂题目怎么循环,条件是什么,然后再改成递归题目,这样的话会让思路更清晰一些。