pta简单实现x的n次方_剖析JavaScript递归的实现原理:堆栈与链表

现在我们更加深入地研究函数。

我们的第一个主题是 递归(recursion)

递归是一种编程模式,在一个任务可以自然地拆分成多个相同类型但更简单的任务的情况下非常有用。或者,在一个任务可以简化为一个简单的行为加上该任务的一个更简单的变体的时候可以使用。或者,就像我们很快会看到的那样,处理某些数据结构。

当一个函数解决一个任务时,在解决的过程中它可以调用很多其它函数。在部分情况下,函数会调用 自身。这就是所谓的 递归

两种思考方式

简单起见,让我们写一个函数 pow(x, n),它可以计算 x 的 n 次方。换句话说就是,x 乘以自身 n 次。

pow(2, 2) = 4pow(2, 3) = 8pow(2, 4) = 16

有两种实现方式。

  1. 迭代思路:使用 for 循环:
function pow(x, n) {  let result = 1;  // 再循环中,用 x 乘以 result n 次  for (let i = 0; i < n; i++) {    result *= x;  }  return result;}alert( pow(2, 3) ); // 8
  1. 递归思路:简化任务,调用自身:
function pow(x, n) {  if (n == 1) {    return x;  } else {    return x * pow(x, n - 1);  }}alert( pow(2, 3) ); // 8

请注意,递归变体在本质上是不同的。

当 pow(x, n) 被调用时,执行分为两个分支:

              if n==1  = x             /pow(x, n) =                           else     = x * pow(x, n - 1)
  1. 如果 n == 1,所有事情都会很简单,这叫做 基础 的递归,因为它会立即产生明显的结果:pow(x, 1) 等于 x。
  2. 否则,我们可以用 x * pow(x, n - 1) 表示 pow(x, n)。在数学里,可能会写为 xn = x * x^(n-1)。这叫做 一个递归步骤:我们将任务转化为更简单的行为(x 的乘法)和更简单的同类任务的调用(带有更小的 n 的 pow 运算)。接下来的步骤将其进一步简化,直到 n 达到 1。

我们也可以说 pow 递归地调用自身 直到 n == 1。

比如,为了计算 pow(2, 4),递归变体经过了下面几个步骤:

  1. pow(2, 4) = 2 * pow(2, 3)
  2. pow(2, 3) = 2 * pow(2, 2)
  3. pow(2, 2) = 2 * pow(2, 1)
  4. pow(2, 1) = 2

因此,递归将函数调用简化为一个更简单的函数调用,然后再将其简化为一个更简单的函数,以此类推,直到结果变得显而易见。

递归通常更短

递归解通常比迭代解更短。

在这儿,我们可以使用条件运算符 ? 而不是 if 语句,从而使 pow(x, n) 更简洁并且可读性依然很高:

function pow(x, n) {  return (n == 1) ? x : (x * pow(x, n - 1));}

最大的嵌套调用次数(包括首次)被称为 递归深度。在我们的例子中,它正好等于 n。

最大递归深度受限于 JavaScript 引擎。对我们来说,引擎在最大迭代深度为 10000 及以下时是可靠的,有些引擎可能允许更大的最大深度,但是对于大多数引擎来说,100000 可能就超出限制了。有一些自动优化能够帮助减轻这种情况(尾部调用优化),但目前它们还没有被完全支持,只能用于简单场景。

这就限制了递归的应用,但是递归仍然被广泛使用。有很多任务中,递归思维方式会使代码更简单,更容易维护。

执行环境和堆栈 The execution context and stack

现在我们来研究一下递归调用是如何工作的。为此,我们会先看看函数底层的工

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值