递归
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 }