引子

从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事讲的是从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事讲的是从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事讲的是从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事讲的是从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事讲的是......

这个例子,如果用java程序来演示,会是这个样子:

public class Hello {
	public static void main(String[] args) {
		sayStory();		  
	}
	
	static void sayStory(){
		System.out.println("从前有座山,山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事,故事讲的是");
		sayStory();
	}	
}

程序运行结果:

故事在一直讲下去。

看一下java代码中,在方法sayStory()中又调用了sayStory()。

递归概述

什么是递归

  递归,英文为Recursion, 在计算机科学中,递归指得是在函数的定义中使用函数自身。 递归,包含了两个意思:递 和 归。递是只传递下去,归是指归来,也就是说,递归有去也有回。 那么,上面的讲故事的程序,算递归程序吗? 在方法sayStory()中又调用了sayStory(),符合递归的一个条件,即传递,但是,这个程序,没有归来,所以,程序会一直运行下去,直到资源耗尽,程序出错:

因此,这不是个完整的递归程序。 递归要素 首先,递归必须要申明一个函数,且在函数中调用自身。 另外,递归要有明确的终止条件,递归就是有去有回,必然有一个明确的重点,到达这个终点后,就不再往下递,而是开始往回归来。

递归的内涵

​ 递归的核心思想,就是把规模大的问题转化为规模小的相似的子问题来解决。在函数实现时,因为解决大问题的方法和解决小问题的方法往往是同一个方法,所以就产生了函数调用它自身的情况,这也正是递归的定义所在。 考虑一下,递归的数学模型,很像数学归纳法。数学归纳法适用于将解决的原问题转化为解决它的子问题,而它的子问题又变成子问题的子问题。归纳法解决数学问题一般分为下面3个步骤: 1:步进表达式:问题演算成子问题的表达式 2:结束条件:什么时候可以不再使用步进表达式 3:求解表达式:在结束条件下能够直接计算返回值的表达式

比如,斐波那契数列,使用数学归纳法,3个步骤为: 1: 推导出计算表达式: F(n)=F(n-1)+F(n-2) (n≥3) 2:结束条件:n=1,n=2时 3:求解表达式: F(1)=F(2)=1

递归的编程模型

   明确了递归的数学模型后,我们就要看,如果通过编程来实现递归。一般的,有两种编程模型:

模型一: 先处理问题,然后再往下传递 递归函数(大规模){

    if (end_condition){      // 递归终止条件
        end;   
    }else{
        solve;             // 处理问题
        递归函数(小规模);  // 分解问题规模,传递下去
    }
}

模型二: 在归来的过程中处理问题 递归函数(大规模){

    if (end_condition){      // 递归终止条件
        end; 
}else{ 
    递归函数(小规模);  //分解问题规模,传递下去
        solve;            // 归来,处理问题
    }
}

下面,演示一下,使用递归的编程模型,解决斐波那契数列问题。 首先,需要什么一个函数,问题规模为n,问题的结果为一个整数。 则函数可以声明为:int fib(int n) 然后,确定终止条件: n=1,n=2时 3:求解表达式: F(n)=F(n-1)+F(n-2) (n≥3) F(1)=1,F(2)=1

则代码如下:

案例演示

阶乘

阶乘n!的数学定义: n!=1234…..(n-1)n,并规定 1!=1。 因此,2!=21=2(1!),3!=3*(21)=3(2!), 4!=4*(321)=4*(3!) 5!=5*(4321)=54! 根据规律,可以推断出: n!=n*(n-1)!,这就是阶乘的递归公式。 并且可以明确递归的终止条件n=1,终止时的值为1。

下面,想一下,如何用java程序来实现呢? 递归函数原型,可以什么为:int factorial(int n); 则函数的递归调用表达式为: factorial(n)=n* factorial(n-1)

具体代码如下:

public class Hello {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入n:");
		int n = sc.nextInt();
		int f = factorial(n);
		System.out.println("结果是:" + f);
	}

	static int factorial(int n) {
		if (n == 1)
			return 1;
		else
			return n * factorial(n - 1);
	}
}

更多案例,请看下一章节。