[Java] What is the recursive call? (Recursion)

/*递归调用Recursion==============================================================
先:依次降解,直至可解.
再:依次代入,直至求出.
在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。
递归调用需要在栈中创建多个栈指针,效率会比较低.
所以,在实际开发中,对此可以不用递归就能解决的方法,一般不使用递归.比如阶乘比较大时.
另外,递归要用对场合.

范例1:求n!
分析,由于n!=n*(n-1)!
eg: 5! 
	|
	5*4!
	  |
	  4*3!
		|
		3*2!
		  |
		  2*1!
			|
			1!=1
这里从上往下的推算是第1步:依次降解,直至可解.
得至1!=1后,从下往上推算是:依次代入,直至求出.
*/

//使用递归方法求: n! (n的阶乘factorial)
public class Recursion {
	public static void main(String args[]){
		System.out.println(fac(5)); //120
	}
	public static long fac(int x){ //返回值可能比较大,定义为long
		if(x==1){	//此处也是递归结束的条件,没有此条件,此会无限地调用下去,并抛出StackOverflowError
			return 1;
		}else{
			return x*fac(x-1); //递归调用,自己调用自己
			//System.out.println(x*fac(x-1)); //假如加上这一行会出现:Unreachable code错误,表示不可能执行到的编码.
		}
	}
}
/*
该调用的说明:
每次方法的调用都会创建一个栈指针,即使是同一个方法的多次调用也会创建多个栈指针.
先:依次降解,直至可解: 从栈底开始根据调用往上一个个入栈.
   main方法调用fac(5),fac(5)方法调用fac(4)...直到调用fac(1)时,建立了如下图的栈.
   调用到fac(1)时,其他调用都还没有结束.
   Thread [main] Stack
	┌		   	 ┐
	│x = 1 fac(1)│6
	├────────────┤
	│x = 2 fac(2)│5
	├────────────┤
	│x = 1 fac(3)│4
	├────────────┤
	│x = 1 fac(4)│3
	├────────────┤
	│x = 1 fac(5)│2
	├────────────┤
	│x = 1  main │1
	└────────────┘
再:依次代入,直至求出.
   到fac(1)时,得到结果1,并返回给它的调用者fac(2).
   Thread [main] Stack
	┌			 ┐
	│			 │1. fac(1)给调用它的fac(2)返回1,然后出栈
	├────────────┤
	│x = 2 fac(2)│2. fac(2)给调用它的fac(2)返回2,然后出栈
	├────────────┤
	│x = 1 fac(3)│3. ......
	├────────────┤
	│x = 1 fac(4)│4. .....
	├────────────┤
	│x = 1 fac(5)│5. .....
	├────────────┤
	│x = 1  main │6. fac(2)给调用它的main返回120,然后出栈
	└────────────┘
*/

/*
范例2:求1+2+3+..+100
*/
//使用递归方法求: 1+2+3+...+100
public class Recursion {
	public static void main(String args[]) {
		System.out.println(sum(100));
	}
	public static long sum(int x){
		if(x==1){
			return 1;
		}else{
			return x+sum(x-1);
		}
	}
}

/*另外,递归要用对场合-------------------------------------------
斐波那契数列:1,1,2,3,5,8,...计算斐波那契数列的第n项的值:
*/
/*计算斐波那契数列的第n项的值:
*/
public class Recursion {
	public static void main(String args[]) {
		System.out.println(fib(50));
	}
	public static long fib(int n){
		if( (n==1)||(n==2) ){
			return 1;
		}else{
			return fib(n-1)+fib(n-2);
		}
	}
}
/*
程序输出:12586269025
这个结果是对的,但时计算了很长时间,分析一下发现了问题:
fib(50)要调用fib(49)\fib(48);
			 fib(49)要调用fib(48)\fib(47);
						  fib(48)要调用fib(47)\fib(46);....
其中存在了大量的重复调用,据计算一共是251亿多次.所以才耗费了这么长的时间.
所以,这是一个非常差的方法.可以使用下面的方法:
使用一个数组来存放数列,为了下标n就能表示第n项,我们设置了数组的第1个元素在程序中不使用.
*/
public class Recursion {
	public static void main(String args[]) {
		int n = 50;
		long a[] = new long[n+1];
		a[0]=0;
		a[1]=1;
		a[2]=1;
		for(int i=3; i<n+1; i++){
			a[i]=a[i-1]+a[i-2];
		}
		//下面打印出所有的数列:
		for(int i=1; i<n+1; i++){
			System.out.println(a[i]);
		}
	}
}








Published 15 original articles · won praise 1 · views 4125

Guess you like

Origin blog.csdn.net/jsqdsq/article/details/78509768