JavaScript 中的递归函数是如何工作的?


本文将教你如何使用递归方法创建一个 JavaScript 递归函数——**一个调用自身的函数**。递归的过程就是函数调用自身。递归函数是指反复调用自身的函数。递归函数中总是包含一个停止调用自身的条件,否则它将无限地调用自身。递归函数通常用于将一个大的问题分解成更小的子问题。递归函数常见于二叉树、图等数据结构以及二分查找、快速排序等算法中。

递归函数并不总是清晰或容易理解。如果你理解以下几点,你将更快地阅读和理解递归函数。首先,你应该始终确定函数的基本情况(base case)。向函数传递参数,以便它可以直接到达基本情况。确定哪些输入至少会调用一次递归函数。

阅读和编写递归函数几乎相同。创建一个可以通过其参数访问的普通函数,并具有基本情况。向函数传递参数,以便它可以直接调用基本情况。传递启动递归调用的后续参数。

让我们看看不同的方法来了解递归在 JavaScript 中是如何工作的。

使用递归计算阶乘

正数 n 的阶乘由下式给出:

n 的阶乘 (n!) = 1 * 2 * 3 * 4 *... * n

负数的阶乘不存在。0 的阶乘为 1。

语法

以下是递归函数的语法:

function recursion() {
   if(condition) {
      recursion();
   } else {
      // stop calling recursion()
   }
}
recursion();

示例

在下面的示例中,我们将演示如何在 JavaScript 中使用递归查找数字的阶乘。我们创建一个名为 `fact()` 的函数,带有一个参数“b”,该参数从主函数中获取值为 6。首先,我们检查数字是否等于 0。如果为真,则程序将返回 1。在 else 语句中,我们将检查 b*fact(b-1),大致相当于 6*(6-1)。在下一个递归中,它将是 5*(5-1),依此类推。通过这种方式,函数将继续计算数字的阶乘。函数在递归结束后打印输入数字的阶乘值。

<html>
<head>
   <title> Factorial using Recursion </title>
</head>
<body>
   <h2> Factorial using JavaScript recursion </h2>
   <script>
      // program to find the factorial of a number
      function fact(b) {
         // if number is 0
         if (b === 0) {
            return 1;
         }
         // if number is positive
         else {
            return b * fact(b - 1);
         }
      }
      const n = 6;
      // calling factorial() if num is non-negative
      if (n > 0) {
         let res = fact(n);
         document.write(`The factorial of ${n} is ${res}`);
      }
   </script>
</body>
</html>

在上面的输出中,用户可以看到递归后我们计算出的数字阶乘为 720。

循环递归

在这种技术中,我们将观察到函数1(a) 调用函数2(b),函数2(b) 调用函数3(c),函数3(c) 调用函数1(a),从而形成一个循环。

示例

在下面的示例中,我们创建了三个函数来理解这种方法。首先,我们创建一个名为 `funA()` 的函数,它带有一个名为 n 的变量。我们检查此值是否小于 0 并执行某个操作 (n-1)。此函数调用 `funB()`,在检查 n 是否大于 2 后执行某个操作 (n-2)。然后 `funB()` 调用另一个函数 `funC()`,该函数接收参数 (n)。这就是嵌套递归的工作方式。

<html>
<body>
   <h2> Nested Recursion using JavaScript </h2>
   <script>
      // JavaScript program to show Cyclic Recursion
      function funA(n) {
         if (n > 0) {
            document.write(n.toFixed(0) + "</br>");
            // Fun(A) is calling fun(B)
            funB(n - 1);
         }
      }
      function funB(n) {
         if (n > 1) {
            document.write(n.toFixed(0) + "</br>");
            // Fun(B) is calling fun(C)
            funC(n - 2);
         }
      }
      function funC(n) {
         if (n > 1) {
            document.write(n.toFixed(0) + "</br>");
            // Fun(C) is calling fun(A)
            funA(n);
         }
      }
      funA(5);
   </script>
</body>
</html>

用户可以观察到,给 `funA()` 的第一个值为 5。然后执行 (n-1) 得到 4。然后 (n-2) 得到 2。类似地,(n) 得到 2。然后我们得到 (n-1) 为 1,传递给 `funB()`。

嵌套递归

在这种递归中,参数将作为递归调用由递归函数发送。“递归中的递归”就是这个意思。为了理解这种递归,让我们看一个例子。

语法

func(n)
{
   Return func(func(n-1))
}

参数

  • n − 用于在嵌套递归中执行任何计算的参数。

示例

在这个例子中,我们创建一个名为 `fun()` 的函数,它从驱动程序中获取值为 **num**。这里我们创建了一个名为 `nested` 的函数,它接受一个整数参数。在这个函数内部有一个 if-else 块,它检查 **num**> 100,如果是则返回 **num** - 10,否则返回 `nested(nested(num + 11))`。

<html>
<body>
   <h3> JavaScript program to show Nested Recursion </h3>
   <script>
      function fun(num){ 
         // A recursive function passing parameter
         // as a recursive call or recursion
         // inside the recursion
         if (num > 100)
            return (num - 10);
         else
            return fun(fun(num + 11));
      }
      var r;
      r = fun(98);
      document.write(r);
   </script>
</body>
</html>

输出显示作为 `num` 传递的 98 将如何被递归调用,最终得到 91 的值。

结论

这三种方法阐明了执行递归的不同方法。第一种方法是一种简单的方法,帮助用户计算数字的阶乘。第二种方法有助于了解如何使用循环递归技术使用三个函数执行递归。第三种方法展示了嵌套递归如何在 JavaScript 中发生。

更新于:2022年7月22日

568 次浏览

启动您的 职业生涯

完成课程获得认证

开始学习
广告