递归
(本文节选自http://www.cnblogs.com/vamei/archive/2013/03/30/2989930.html)
递归(recursion)是计算机中的重要概念,它是指一个计算机程序调用其自身。为了保证计算机不陷入死循环,递归要求程序有一个能够达到的终止条件(base case)。比如下面的程序,是用于计算高斯求和公式(1+2+…+n):
int f(n)
{
if (n == 1) {
return 1; // base case
}
else {
return f(n-1) + n; // induction
}
}
递归是数学归纳法在计算机中的程序实现。使用递归设计程序的时候,我们设置base case,并假设我们会获得n-1的结果,并实现n的结果。这就好像数学归纳法,我们只关注初始和衔接,而不需要关注具体的每一步。
栈
递归是用栈(stack)数据结构实现的。计算f(n),需要f(n-1);计算f(n-1),需要f(n-2)……。每个问题的解答都依赖于下一个问题,直到我们找到第一个可以回答的问题: f(1)的值是什么?我们用栈来保存我们在探索过程中的疑问。C语言中,函数的调用已经是用栈记录离场情境和返回地址。递归是函数对自身的调用,所以很自然的,递归用栈来保存我们的“疑问” 。
我们假设栈向下增长。首先,我们调用f(100),那么当执行到
return f(n-1) + n;
f(100)暂停执行,并记录当前的状态,比如n的值,当前执行到的位置。随后调用f(99),栈增加一个frame,直到调用f(98) … 栈不断增长,直到f(1)。f(1)得到结果1,并返回给f(2)。f(1)栈frame删除,转移到f(2)frame情境中继续执行
return f(n-1) + n;
然后返回给f(3) … 直到f(99)返回给f(100),并执行
return f(n-1) + n;
返回f(100)的值,得到结果。
上述过程是C编译器自动完成的。在实现递归算法时,也可以自行手动实现栈。这样可以得到更好的运行效率。