递归算法

一、题目分析
用递归方法设计下列各题,并给出每道题目的递归出口(递归结束的条件)和递归表达式。同时考虑题目可否设计为非递归方法,如果可以,设计出非递归的算法。
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),先搞懂题目怎么循环,条件是什么,然后再改成递归题目,这样的话会让思路更清晰一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿哈哈~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值