【问题标题】:Where do recursive functions end?递归函数在哪里结束?
【发布时间】:2021-11-16 13:06:15
【问题描述】:
#include <stdio.h>

int factorial(int n);
void main()
{
    int n;
    printf("Enter your number : " );
    scanf("%d",&n);
    if(n <= 1)
    {
        printf("The factorial of the number n is ",n);
    }
    else
    {
        int res = factorial(n);
        printf("The result is %d\n",res);
    }
}
int factorial(int n)
{
    if(n <= 1)
        return 1;
    return n * factorial(n-1);
}

我第一次做一个递归函数的概念,我对递归的概念几乎掌握了 65%。在上面的程序中,我编写了一个阶乘递归函数,它运行正常,我得到了输出,但我试图思考递归在哪里结束

例如,我输入了 5:

The result is 120

但我想要的主要是为什么它在 0 之后不继续,如果 n

【问题讨论】:

  • 65% - 你是怎么得出这个数字的?只是好奇,:)
  • @SouravGhosh 73% 的统计数据是现场制作的。
  • n &lt;= 1 时,您只返回1,而不是1 * factorial(n - 1)。由于此处未调用factorial,因此不会发生n = 0, -1, ...
  • @VLAZ 有 87% 的错误概率,而 67% 的人在 91% 的时间内都这样做了。
  • @Sourav Ghosh 我收到了号码

标签: c recursion


【解决方案1】:

假设您已经调用factorial(3),那么调用链将是这样的:

factorial(3)  // Initial call
    factorial(2);
        factorial(1);
            return 1;  // No more recursion
        return 2 * 1;  // 1 is the result of factorial(1)
    return 3 * 2;  // 2 is the result of factorial(2)

factorial(3) 的结果将是 6 (3 * (2 * 1))。

【讨论】:

  • 天哪....好像最里面的函数(就递归而言)会先执行,然后返回最外面的函数返回值?
【解决方案2】:

总之我真的不知道递归在哪里结束..

它以return 1; 语句结束:

int factorial(int n)
{
    if(n <= 1)
        return 1;  <---- Here
    return n * factorial(n-1);
}

如果你把它写成这样可能会更清楚:

int factorial(int n)
{
    if(n <= 1)
    {
        // No more recursive calls - just return 1
        return 1;
    }
    else
    {
        // Do recursive call with decremented argument
        return n * factorial(n-1);
    }
}

所以代码一直进行递归调用,直到n 变为 1。然后它返回 1 到前一个递归调用,它返回 2 (2 * 1) 到前一个递归调用,它返回 6 (3 * 2) 到前一个递归调用,返回 24 (4 * 6) .... 等等。

所以最终的结果是这样计算的:

1 * 2 * 3 * 4 * ...
\---/   
  2   * 3
\-------/
    6     * 4
\-----------/
      24

【讨论】:

  • 你简直让我大吃一惊……Common W..and PS这个概念可以用在Java和Python中对吧?
  • @Aryan 我对 java 和 python 不太了解,但我认为它们支持递归调用
  • 阿卡托什的祝福与你同在
【解决方案3】:

来自Recursion

在数学和计算机科学中,一类对象或方法在可以由两个属性定义时表现出递归行为:

  • 一个简单的基本案例(或多个案例) - 一个不使用递归来产生答案的终止场景。
  • 递归步骤 - 一组将所有连续案例减少到基本案例的规则。

因此,终止场景/条件是递归的属性之一,它是递归结束的地方。

在您的程序上下文中:

您的程序正在查找给定数字 n 的阶乘。

非负整数n的阶乘是所有小于或等于n的正整数的乘积:

n ! = n * ( n − 1 ) * ( n − 2 ) * ( n − 3 ) * ..... * 3 * 2 * 1

相当于

n ! = n * ( n - 1 ) !

也就是说,在编写程序计算一个数n的阶乘时,我们必须计算所有正整数的乘积,并在达到1时停止,这是终止条件。

factorial()函数中:

int factorial(int n)
{
    if(n <= 1)
        return 1;
    return n * factorial(n-1);
}

条件if(n &lt;= 1) 是递归函数找到n 的阶乘以及递归函数factorial() 结束的位置的终止条件。

附加

  • 在您的程序中,您缺少此格式说明符 printf()声明:

    printf("The factorial of the number n is ",n);

应该是

printf("The factorial of the number n is %d\n",n);
                                         ^^
  • 请注意,0!1,在进行上述更改后,您的程序 当用户输入数字0 时,将输出为0 错了。

您应该编写函数来计算给定正数n 的阶乘,如下所示:

unsigned int factorial(unsigned int n) {
    if (n == 0) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

并在调用factorial() 之前添加对用户输入的检查。这也会处理0!

  • 使用void 作为main 函数的返回类型不符合 标准。 main函数的返回类型应该是int

【讨论】:

    【解决方案4】:

    要理解简单的递归代码,绘制图表(递归跟踪)很有帮助。我会用颜料画出来,但最好在纸上画。
    假设我们打电话给factorial(3)

    1. 写下函数的调用。(开头是factorial(3)
    2. 问问自己:“退出条件是否满足?”(在你的情况下,条件是if(n &lt;= 1)
      • 如果答案是肯定的,检查返回的内容并写在前面的函数调用下,然后进行下一步。
        你有return 1;所以1被返回。李>
      • 如果答案是否定的,检查返回的内容并写在前面的函数调用下。你有return n*factorial(n-1);,所以第一次返回值将是3*factorial(3-1),等于@987654332 @。 现在返回步骤 1),调用新的函数并重复该过程,直到满足条件。这里的电话是factorial(2)
        您还可以用箭头连接函数调用,使图表更有条理。

    当您的条件满足时,图表应如下所示:

    1. 您现在从下往上:
      写下最底层函数调用的值,并为上面的每个函数调用重复。
      在您的情况下,您首先写出factorial(1)的值,也就是1,然后向上移动,你会看到factorial(2)等于2*factorial(1)。因为你知道factorial(1) 等于1,所以你也知道 factorial(2) 等于 2
      您可以将函数调用向上连接以使图表更有条理。

    你已经完成了。该图应如下所示:

    通过这张图,我们可以准确地知道递归何时停止——何时调用factorial(1)。我们也知道最终结果,即6

    【讨论】:

      猜你喜欢
      • 2015-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-30
      • 2021-06-05
      • 1970-01-01
      相关资源
      最近更新 更多