什么是尾递归调用?

普通递归:每次函数调用时,都会在调用栈上创建一个新的栈帧以保存函数的局部变量、参数和返回地址。随着递归深度的增加,栈会不断增长,可能导致栈溢出错误。

尾递归 :当它在递归调用后不执行任何操作,直接返回递归调用的结果

尾递归调用:是一种特殊的递归形式,其中递归调用是函数的最后一个操作。尾递归将递归调用转换为迭代,从而节省函数调用栈的空间,避免栈溢出。许多编程语言和编译器能够对尾递归进行优化,称为尾递归优化(Tail Call Optimization,TCO)。

举两个例子:阶阶乘函数和斐波那契数列来分别使用普通递归和尾递归方式实现。

1. 阶乘函数

1.普通递归:

function factorial(n: number): number {
    if (n === 0) {
        return 1;
    }
    return n * factorial(n - 1);
}
// factorial(5)的调用过程:
// 5 * factorial(4)
// 5* 4 * factorial(3)
// 5* 4* 3 * factorial(2)
// 5* 4* 3* 2 * factorial(1)
// 5* 4* 3* 2* 1 * factorial(0)
// 5* 4* 3* 2* 1 * 1  ---> 120

2.尾递归

function tailRecursiveFactorial(n: number, acc: number = 1): number {
    if (n === 0) {
        return acc;
    }
    return tailRecursiveFactorial(n - 1, n * acc);
}
// tailRecursiveFactorial(5)的调用过程:
// tailRecursiveFactorial(4, 5)
// tailRecursiveFactorial(3, 20)
// tailRecursiveFactorial(2, 60)
// tailRecursiveFactorial(1, 120)
// tailRecursiveFactorial(0, 120)
// 输出120

在这种实现中,递归调用 tailRecursiveFactorial(n - 1, n * acc) 是函数的最后一个操作,没有其他操作跟在后面,因此是尾递归。

2. 斐波那契数列

1.普通递归:

function fibonacci(n: number): number {
    if (n <= 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}

2.尾递归:

function tailRecursiveFibonacci(n: number, a: number = 0, b: number = 1): number {
    if (n === 0) {
        return a;
    }
    return tailRecursiveFibonacci(n - 1, b, a + b);
}

console.log(tailRecursiveFibonacci(10)); // 输出: 55

3. 尾递归调用的优缺点

优点:

  1. 节省内存:通过优化递归调用,减少调用栈的深度,避免栈溢出
  2. 提高效率:减少函数调用的开销,提升性能。

缺点:

  1. 语言和编译器支持:并非所有编程语言和编译器都支持尾递归优化
  2. 问题复杂度:对于某些复杂问题,尾递归可能不适用,仍需使用其他优化技术。
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值