当一个函数在其定义中直接或间接地调用了自身,我们称之为递归函数。递归函数通常用于处理具有递归结构的数据,例如树、图、链表等。
递归函数可以看作是解决问题的一种方式,一般使用递归函数可以使代码更加简洁、易懂。在实现递归函数时,需要满足两个条件:
递归结束条件(递归基):当递归到某个条件时,需要停止递归,返回结果。
递归调用:递归调用自身处理子问题,将子问题的结果合并为最终结果。
以下是一个简单的例子:计算 n!。
int factorial(int n) {
if (n == 1 || n == 0) { // 递归结束条件return1;
} else {
return n * factorial(n - 1); // 递归调用
}
}
在上面的例子中,当 n=1 或 n=0 时,函数返回 1,这是递归结束的条件,也称为递归基。如果 n>1,则函数将会调用自身来计算 n-1 的阶乘,然后将其乘以 n,这就是递归调用。
下面是另一个例子:求斐波那契数列第 n 项。
int fibonacci(int n) {
if (n == 0) { // 递归结束条件1return0;
} elseif (n == 1) { // 递归结束条件2return1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2); // 递归调用
}
}
在上面的例子中,当 n=0 时,函数返回 0,这是递归结束的条件之一。当 n=1 时,函数返回 1,这是递归结束的条件之二。如果 n>1,则函数将会调用自身来计算 n-1 和 n-2 的斐波那契数列值之和,这就是递归调用。
需要注意的是,递归函数的缺点之一是容易造成栈溢出,因为每次递归调用都会在内存中创建一个新的栈帧。为了避免这种情况,可以使用尾递归,将函数调用的结果传递给下一次函数调用,从而减少栈的使用。