什么是递归

递归是指在函数定义中使用函数自身的方法。经典的递归例子包括阶乘和斐波那契数列。递归有明确的调用自身规律和边界条件。其优点是简化代码,但缺点是可能导致执行效率低和重复计算。优化递归的方法之一是尾调用,通过确保函数内部的最后操作是函数调用,从而减少执行上下文的创建。优化后的阶乘函数利用尾调用来提高效率。
摘要由CSDN通过智能技术生成

定义

摘抄自维基百科:在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。
从字面上的意义来说,就是在一个函数里面调用函数自己本身

经典例子

1.阶乘

  function factorial(n){
    if(n == 1 || n === 0){
      return 1
     }
    return n * factorial(n-1)
  }

2.斐波那契数列

  function fb(n){
    if(n == 0 || n == 1){
      return n
    }
    return fb(n-1) + fb(n-2)
  }

分析

由两个例子我们可以看出,在函数内,他还会再调用函数自己本身,而调用的那一层,可能就有值可以return出来,也可能再次调用函数本身。但无论是连续调用几次,他都有一个边界,像阶乘的边界是n=1,斐波那契数列的边界时n=2。

由此我们可以总结出递归的特点:
1.有规律,有一个调用函数自己本身的过程。
2.有出口,有边界条件使得递归结束。

优缺点

优点:
能够将多次重复计算的过程用一小段代码表示出来,让代码看起来更为简洁
缺点:
1.递归是一个一次或多次调用函数本身的过程,而在函数调用时,都要在栈内存中分配空间来存储变量、参数、地址等,这些都回消耗时间和空间,从而导致执行效率低下。
2.递归存在很多重复计算的过程,有可能会出现重叠计算,这样重复的计算也会导致效率低下。

优化方法

递归就是不断调用函数的过程。而当执行一个函数时,就会创建一个执行上下文,并压入执行上下文栈,当函数执行完毕时,执行上下文会从执行上下文栈中弹出。不断调用函数的过程,javascript会不断重复上面的过程,这是非常损耗的。我们需要一个方法来优化这个过程,这个方法就是尾调用

尾调用

尾调用的意思就是函数内部最后一个动作是函数调用,返回值只有函数,没有其他运算过程。
eg:
尾调用:

function a(x){
  return f(x)
}

非尾调用:

function b(x){
    return f(x) + 1
}

第一个函数执行时,虽然调用了一个函数,但原来的函数a已经执行完毕,执行上下文会弹出,再压入另外一个函数f的执行上下文。这个过程中相当于只压入一个执行上下文。也就是说函数a的执行上下文弹出后,才会压入函数f的执行上下文。
而第二个函数执行时,在调用函数的过程中,函数b需要等函数f执行完与1相加后,才有返回值,这个过程相当于压入了两个执行上下文。
尾调用的作用就是减少创建执行上下文的个数。

优化例子

我们将阶乘函数优化一下:

function factorial(n,sum){
    if(n == 1 || n === 0){
      return first
     }
    return factorial(n-1,n * sum)
  }

其中sum一开始的值为阶乘的最后一个数1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值