当调用递归方法来解决问题时,该方法实际上只知道如何解决最简单的情况,即基本情况。
递归调用就是将不知道如何处理的部分模拟成原始问题,于是便可以调用自己的新副本来解决问题,一系列越来越小的问题最终会成为基本情况。该方法识别了基本情况后,向方法的前一个副本返回一个值,经过一系列的返回,直到原始方法向调用者返回最终的的值为止。
常见错误:忽略了基本情况,或者不正确地编写了递归步骤而未包含基本情况,将导致无限递归,最终耗尽内存。
大多数编程语言的弱点,即语言不易扩展以处理各种应用的特定需求。Java是一种可扩展语言,允许我们创建需要的任意大的整数。
Java语言中运算符的操作数计算顺序是从左到右。
递归和迭代都是基于单一的控制结构:迭代使用一种重复结构(如for,while,do/while),递归则使用一种选择结构(如if,if/else,switch)。
两者都涉及到重复,迭代显式地使用一个重复结构,递归则进行重复的方法调用。
终止:递归在识别基本情况后终止,迭代则是在计数器达到使循环条件失效的值后终止。
迭代一般发生在一个方法内,于是重复的方法调用和过度的内存分配都可以忽略。而递归调用每次都将创建方法的另一个副本,可能占用相当大的内存。
因此能用迭代,就不用递归,特别是要求高性能的情况下。如果递归方法可以更自然地反映问题,别且产生易于理解和调试的程序时,就可以选择递归。
编写了一个阶乘的小例子。
// Recursive factorial method
import java.applet.Applet;
import java.awt.Graphics;
public class FactorialTest extends Applet{
public void paint( Graphics g )
{
int yPos = 25;
for ( int i = 1; i <= 10; i++)
{
g.drawString( i + "! = " + factorial( i ), 25, yPos);
yPos += 15;
}
}
// factorial method definition
public long factorial( long x )
{
if ( x <= 1 )
return 1;
else
return x * factorial( x - 1 );
}
}
结果如图所示:
斐波那契数列
// Fibonacci
import java.applet.Applet;
import java.awt.Event;
import java.awt.Label;
import java.awt.TextField;
public class Fibonacci extends Applet{
Label label_num, label_result;
TextField text_num, text_result;
// setup the graphical user interface components
public void init(){
label_num = new Label( "Enter a number and press Enter:" );
label_result = new Label( "The result:" );
text_num = new TextField( 10 );
text_result = new TextField( 20 );
add( label_num );
add( text_num );
add( label_result );
add( text_result );
}
// process to the action
public boolean action( Event e, Object o )
{
long number, fibonacciVal;
number = Long.parseLong( text_num.getText() );
showStatus( "Calculating..." );
fibonacciVal = fibonacci( number );
showStatus( "Done" );
text_result.setText( Long.toString( fibonacciVal ) );
return true;
}
// fibonacci method definition
public long fibonacci( long x )
{
if ( x == 0 || x == 1 )
return x;
else
return fibonacci( x - 1 ) + fibonacci( x - 2 );
}
}