java算法:递归算法

递归算法时通过解决相同问题的一个或几个小例子来解决问题的算法。在java中,实现递归方法就是调用自身的方法。

例1:阶乘函数递归实现

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

for(t = 1, i = 1; i <=N; i++){
	t *= i;
}

是等价的,一个递归程序总可以转换成执行相同计算的非递归程序。同样,可以用递归来表示设计循环的任何计算。使用递归能以简洁的形式表达复杂的算法,且不失效率。如:阶乘函数的递归实现可以避免使用局部变量。递归的开销在于编程系统中支持方法调用的机制,它使用了一个等同的内嵌堆栈。

例2:可疑的递归程序

static int puzzle(int n){
	if(n == 1){
		return 1;
	}
	if(n % 2 == 0){
		return puzzle(n/2);
	}else{
		return puzzle(3 * n + 1);
	}
}

与阶乘函数递归实现相比,这个是不能证明的。但是,该程序确实可以终止的。

例3:欧几里得算法

static int gcd(int m, int n){
	if(n == 0){
		return m;
	}
	return gcd(n, m%n);
}

对于欧几里得算法,递归的深度取决于参数的算术性质(已知是对数级的)。

例4:对前缀表达式求值的递归程序

static char[] a;
static int i;
static int eval(){
	int x = 0;
	while(a[i] == ' '){
		i++;
	}
	if(a[i] == '+'){
		i++;
		return eval() + eval();
	}
	if(a[i] == '*'){
		i++;
		return eval() * eval();
	}
	while((a[i] >= '0')&&(a[i]<= '9')){
		x = 10 * x + (a[i++] - '0');
	}
	return x;
}

原则上,可用对等的递归程序代替人任何for循环。但通常,用递归程序来表达运算比for循环更自然。递归的深度是指在整个运算过程中方法调用的最大的嵌套次数。

例5:链表递归函数

简单的链表处理任务可以使用递归方式,但可能不试用于巨型链表,因为递归的深度可能与链表的长度成比例。

1. int count(Node h){   
2.     if(h == null){   
3.         return 0;   
4.     }   
5.     return 1 + count(h.next);   
6. }   
7. void traverse(Node h){   
8.     if(h == null){   
9.         reurn;   
10.     }   
11.     h.item.visit();   
12.     travrese(h.next);   
13. }   
14. void traverseR(Node h){   
15.     if(h == null){   
16.         reurn;   
17.     }   
18.     travreseR(h.next);   
19.     h.item.visit();   
20. }   
21. Node remove(Node h, Item v){   
22.     if(h == null){   
23.         return null;   
24.     }   
25.     if(eq(h.item,v)){   
26.         return remove(h.next,v);   
27.     }   
28.     h.next = remove(h.next,v);   
29.     return h;   
30. }