定义:
一个方法可以调用另一个方法来帮助它完成目标。同样,一个方法也可以调用它自身以完成目标。
递归:一种允许方法调用该方法自身的编程技术。
能否递归的编程的关键在于能否递归的思考。
递归体包含两部分:递归部分和非递归部分,非递归部分作为称为基本情形,是递归的统一出口,起到终止递归的作用。如果一个递归没有定义非递归部分,这种递归就是无穷递归,类似于无穷循环,只不过这时是递归定义的内部出现了“循环”。
有一些问题可以用递归解决,也就可以用迭代解决。
递归是有些问题最优雅最恰当的解决方式,但是解决有些问题递归并没有迭代那么直观。不过有些情况下,迭代会过于复杂,递归可以创造相对短小且优雅的程序。
例子:
1到n的累加器:
递归实现:
public int sum(int n){
int res = 0;
if(n == 1){
res = 1;
}else{
res = n + sum(n - 1);
}
return res;
}
迭代实现:
public int sum(int n){
int res = 0;
for(int i = 0; i <= n; i++){
res += i;
}
return res;
}
递归可以分为直接递归和间接递归。
方法调用方法自身叫直接递归。方法调用另一个方法,另一个方法继续调用其它方法,最后调用的那个方法再调用第一个方法,依次类推,这样的递归叫间接递归。如f1调用f2,f2调用f3,f3调用f4,f4再调用f1就属于间接递归。
间接递归的例子:
public int f1(int x) {
if (x <= 0) return x;
return f2(x);
}
public int f2(int y) {
return f1(y - 1);
}
递归优雅的极致展现:
汉诺塔例子:
在汉诺塔问题中有3根竖直的柱子和一组圆盘,圆盘中间有一个孔,这样它们就能够在柱子上滑动,每一张圆盘的直径都不同。开始时候,所有圆盘按照直径大放下面依次放在一个柱子上。
汉诺塔问题的目标就是把所有圆盘从初始柱子(start)移动到最终的柱子(end)上,可以已用临时柱子(temp)作为辅助。
移动必须遵循的原则:
1.一次只能移动一个盘子;
2.不能将大的圆盘放到小的圆盘上面;
3.所有圆盘都必须放在柱子上。
将一叠圆盘(N个)从start移动到end的解决方法:
1.将最上方的N-1个圆盘从start移动到temp;
2.将第N个圆盘从start移动到end;
3.将N-1个圆盘从temp移动到end。
HanoTower.java
/*
*Created on 2016年5月26日
*Copyright 2016 Yong Cai Limited crop. All Rights Reserved
*
*728**80@qq.com
*/
package org.cy.com;
public class HanoTower {
private int totalDisks;
public HanoTower(int disks){
this.totalDisks = disks;
}
public void solve(){
moveTower(totalDisks, 1, 2, 3);
}
private void moveTower(int diskNums, int start,int temp, int end){
if(diskNums == 1){
moveOneDisk(start, end);
}else{
moveTower(diskNums - 1, start, end, temp);
moveOneDisk(start, end);
moveTower(diskNums - 1, temp, start, end);
}
}
private void moveOneDisk(int start, int end){
System.out.println("move from " + start + " to " + end);
}
}
Main.java
/*
*Created on 2016年5月26日
*Copyright 2016 Yong Cai Limited crop. All Rights Reserved
*
*728**80@qq.com
*/
package org.cy.com;
public class Main {
public static void main(String[] args) {
HanoTower ht = new HanoTower(2);
ht.solve();
}
}