递归是每位程序学习人员绕不过的一个重要的设计思想,它很简单却足够强大!不过,最近我在研究迷宫求解问题时却对其中关于图形节点的回溯感到很迷惘,翻了很多资料也想了很久终于知道问题出在哪儿了!老师们讲递归很少有讲它的具体原理的,本文我将从“阶乘”这个很经典的数学问题入手,深入浅出地透视一下递归的原理,先声明一下,它是基于堆栈这种数据结构的!
对于非递归函数,外部程序在调用它们前,系统要保存以下两类信息:
1-外部程序的返回地址;
2-外部程序的变量当前值。
当执行完被调用函数,返回外部程序前,系统首先要恢复外部程序的变量当前值,然后返回外部程序的返回地址。递归函数被外部程序调用时,系统要做的工作和非递归函数被调用时系统要做的工作在形式上类同,只是实现方法不同而已。
递归函数的执行过程具有三个特点:1。函数名相同,2。不断地自调用,3。最后被调用的函数要最先被返回。
系统用于保存递归函数调用信息的堆栈叫“运行时栈”,每一层递归调用所需保存的信息构成运行时栈的一个记录。
事例分析:
f(n=1) if(n=0)
f(n)=n*f(n-1) if(n>1)
以上是阶乘的数学表达式,下面我们用程序来实现它:
public class Factorial {
public static long fact(int n)throws Exception{
int x;
long y;
if(n<0){throw new Exception("parameter error!");}
if(n==0)
{
System.out.println("n="+n);
return 1;
}
else {
x=n-1;
System.out.println("n="+n+" x="+x);
y=fact(x);
//System.out.println("n="+n+" x="+x+" y="+y);
System.out.println("fact(x)->x="+x);
return n*y;
}
}
public static void main(String args[])
{
int n=2;
long fn;
try{
fn=fact(n);
System.out.println("fn="+fn);
}
catch(Exception e){System.out.println(e);}
}
}
结果将如下所示:
n=2 x=1
n=1 x=0
n=0
fact(x)->x=0
fact(x)->x=1
fn=2
我们来看看以上程序是如何在堆栈中运作的:
未完(堆栈最好用图形来表式的,不过,这会儿我这快没电了,有空再来把堆栈流程图填上,有兴趣的朋友可以自己跑下上面的程序!)