递归作为一种程序设计中使用频繁的思想和方法,熟话说就是自己调用自己,不仅方便灵活,而且可以简化代码。递归的实现在很大程度上归功于栈的机制,因为函数在每次执行时都从栈上获得了它的形参的私有副本和局部变量,这些变量位于栈的不同位置,在函数执行过程中,函数原来的形参和变量不会受到干扰,所以递归能够正确的执行并得到预期的结果。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
下面举个简单的例子,数的阶层常常是采用递归的方法来求解:
int foo(int n)
{
cout<<&n<<endl;
if (n==1)
{
return 1;
}
else
{
return n*foo(n-1);
}
}
1)递归前进段
在上面的函数中,假设n=5,此时,n!=1,则执行else语句,返回n*foo(n-1);由于n-1!=1,所以继续执行else语句,返回n*(n-1)*foo(n-2),如此执行下去,直到n==1(在递归前进的过程中,编译器都会复制形参的副本)。
2)递归返回段
当然后遇到终止条件,则停止递归的深入,进行递归的返回。因为n==1时,返回1;所以foo(1)=1; 而foo(2)=2*foo(1); f(3)=3*foo(2),如此一步一步返回,则得到输入n=5时的值foo(5)=5*foo(4)。
递归函数的设计最主要的是要确保递归的终止条件,在上面的函数中,递归终止的条件是n==1。下面我们来对上面函数执行的结果和过程中的变量n进行分析。
上面函数的第一句cout<<&n<<endl;是用来输出变量n的地址,通过输出可以看到,每次n的地址都不同,即递归函数的每次执行都从栈上获得了它的形参的私有副本和局部变量,这样函数的执行能按照正常的逻辑执行下去。