递归程序设计之赶鸭子问题和角谷定理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_44002167/article/details/90711575
  1. 题目分析

    1,赶鸭子
    假设此人有n只鸭子,每经过一个村子卖出n/2+1只鸭子,由题意知道经过7个村子后还剩2只鸭子,容易推断经过第8个村子后鸭子将会卖完,此即为递归边界。问题是问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子?于是得到一个自变量的递归函数recursiveFun(count),其中count用来记录村子数。
    容易得到下面的递归公式:
    在这里插入图片描述
    2,角谷定理
    求输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。即如果n是偶数,则除以二(n/2);如果n是奇数,则乘以三再加一,(n3+1);观察这个规律,若要得到自然数1,令n/2=1和n3+1=1,得到2和0,显然0是错误的,那么它的上一个数字一定是2。那么要得到自然数1,只需要对得到的新的数字,重复上面的过程,看这个过程中,是否会出现数字2。如果出现数字2,就可以说,这个迭代过程是不发散的,此即为递归边界。
    容易得到下面的递归公式:
    在这里插入图片描述

  2. 算法构造
    说明:在画递归算法流程图前,先弄清楚递归流程图怎么画,以下解释答案来自网络

答:和普通函数的流程图没什么区别,就是在调用递归的时候做一个分支出来指向函数开始位置即可

算法流程图:
赶鸭子递归:
在这里插入图片描述
赶鸭子非递归:在这里插入图片描述
角谷定理递归: 在这里插入图片描述
角谷定理非递归:
在这里插入图片描述
4. 算法实现程序源代码
赶鸭子:

package indi.sixCharpter_program;

public class Duckquestion {
	private static int recursiveFun(int count)//递归算法
	 {
	    if(count==8)
	        return 2;
	    else
	        return 2*(recursiveFun(count+1)+1);
	}
	private static int disrecursiveFun() {//非递归算法
		int n=2;//经过七个村子,鸭子数量为2,第八个村子就是0只
		int d=0;//用来记录鸭子数	
		int i=1;
		while(i<8){//经过七个村子,循环七次
			d=2*(n+1);
			System.out.println("第"+(8-i)+"个村子,此人卖出了"+(d/2+1)+"只鸭子,这个人还有鸭子"+(d/2-1));
			n=d;
			i++;
		}
		return d;
	}
	public static void main(String []args) {
		for(int i=1;i<8;i++)
		System.out.println("第"+i+"个村子,此人卖出了"+(recursiveFun(i)/2+1)+"只鸭子,这个人还有鸭子"+recursiveFun(i)+" ");
		System.out.println("刚开始时候此人有鸭子"+disrecursiveFun()+" ");
	
	}
}

角谷定理问题

package indi.sixCharpter_program;
import java.util.Scanner;

public class ValleyAngletheorem {
	private static int recursiveFun(int n) {//递归算法
		if(n<0)
			System.exit(0);	
		if(n==2) {
			System.out.printf("2 step=");//+(++step)
			return 1;
		}else if(n%2==0) {
			System.out.printf(n+" ");
			return recursiveFun(n/2)+1;
		}	
		else {
			System.out.printf(n+" ");
			return recursiveFun(n*3+1)+1;	
		} 
	}
	private static int disrecursiveFun(int n) {//非递归算法
		int step=0;
		if(n<0)
			System.exit(0);
		while(n!=1) {
			if(n%2==0){
				System.out.printf(n+" ");
				n=n/2;
			}else {
				System.out.printf(n+" ");
				n=n*3+1;
			}
			step++;
		}
		return step;
	}
	public static void main(String []args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		System.out.println("递归:");
		System.out.println(+recursiveFun(n)+" ");
		System.out.println("非递归:");
		System.out.println("STEP="+disrecursiveFun(n)+" ");
		sc.close();
	}
}

  1. 调试、测试及运行结果
    赶鸭子问题
    在这里插入图片描述
    角谷定理问题
    在这里插入图片描述
  2. 经验归纳
    递归问题总结:
    递归是程序直接或者间接调用自身的过程,递归模型由递归出口和递归体两部分组成,分析问题时主要抽象出递归出口和递归体。递归问题一般分为两大类:一类是比较简单的数学上的递归函数,要求算得一个函数值,只需要将递归函数翻译出来即可。第二类为问题为一些实际的问题,没有统一的规律可循,解决问题的关键为充分的理解问题,发现问题中的已知和隐含条件。根据逻辑关系分析此问题为什么为一个递归问题,并由此得到递归出口和函数递归体,从而使问题得到解决。
    编程总结:
    此次上机编程方面没有遇到什么难以解决的问题。通过对实际问题的理解分析得到递归公式,将递归公式转化为递归算法,这个步骤是此次上机的重要组成,围绕这样一条思路能够较为清楚的找准目标。递归函数的边界是一个确定的值,函数体是一个递归式,我觉的应该先找到递归边界,在找函数体。以这两个题目看,边界条件可以通过观察计算得到。

猜你喜欢

转载自blog.csdn.net/qq_44002167/article/details/90711575