/*递归调用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]);
}
}
}
[java]什么是递归调用?(Recursion)
最新推荐文章于 2024-06-13 11:20:13 发布