递归

Java支持递归。

递归是根据自身定义内容的过程。就java编程而言,递归是一个允许方法调用自身的特征。

调用自身的方法被称为递归方法。

 

递归的典型例子是阶乘的计算。N的阶乘是从1到N之间所有整数的乘积。

例如:3的阶乘是1*2*3,也就是6。

 

下面显示了使用递归方法计算阶乘的原理。



1 //一个简单递归的例子
 2 
 3 class Factorial{
 4 
 5 //这是一个递归的方法
 6 
 7 int fact(int n){
 8 
 9 int result;
10 
11  
12 
13 if(n==1){
14 
15 return 1;
16 
17 }else {
18 
19 result = fact(n-1)*n;
20 
21 return result;
22 
23 }
24 
25 }
26 
27 }
28 
29  
30 
31 public class Recursion {
32 
33 public static void main(String[] args) {
34 
35 Factorial f = new  Factorial();
36 
37  
38 
39 System.out.println("3的阶乘是"+f.fact(3));
40 
41 System.out.println("4的阶乘是"+f.fact(4));
42 
43 System.out.println("5的阶乘是"+f.fact(5));
44 
45 }
46 
47  
48 
49 }


 

当方法调用自身时,在堆栈上为新的局部变量和参数分配内存,并且使用这些

新的变量从头开始执行方法的代码。当每次递归调用返回时,将老的局部变量

和参数从堆栈中移除,并将执行控制代码恢复到内部的调用点。

递归的方法被称为”望远镜式”的方法,可以自由伸缩。

许多例程的递归版本,他们的执行速度比与之等价的迭代版本要更慢一些,因为

增加了额外的函数调用负担。对方法进行大量的递归调用可能会导致堆栈溢出。

因为参数和局部变量存储在堆栈中,并且每次新的调用都会创建这些变量的副本。所以可能会耗尽堆栈。

如果发生这种情况,java运行时系统会产生一个异常。但是,除非野蛮的运行

递归,否则不必担心这个问题。

 

递归方法的主要优点是,对于某些算法,使用递归可以创建出比迭代版本更清晰

并且更简单的版本。

当编写递归方法时,在某个地方必须有一条if语句,用于强制方法返回而不在执行递归调用。

如果没有这么做,一旦调用该方法,就永远不会返回。这是使用递归时很常见的一个错误。在开发期间可以随意使用println()语句,从而可以观察将要执行的操作,并且如果发现错误,可以终止执行。

 

 

下面是另外一个递归的示例。递归方法printArray() 打印数组values中的前i个元素。



1 class RecTest{
 2 
 3 int values[];
 4 
 5  
 6 
 7 RecTest(int i){
 8 
 9 values = new int[i];
10 
11 }
12 
13 void printArray(int i){
14 
15 if(i==0){
16 
17 return;
18 
19 }else {
20 
21 printArray(i-1);
22 
23 System.out.println("["+(i-1)+"]"+values[i-1]);
24 
25 }
26 
27 }
28 
29 }
30 
31 public class Recursion2 {
32 
33 public static void main(String[] args) {
34 
35 RecTest ob = new RecTest(10);
36 
37  
38 
39 int i;
40 
41 for (i = 0;  i<10; i++) {
42 
43 ob.values[i] = i;
44 
45 ob.printArray(10);
46 
47 } 
48 
49 }
50 
51 }