繁体   English   中英

递归循环(C#)

[英]Recursive loop (C#)

有人可以向我解释吗? 我在C#中编写了一个函数来计算数字的阶乘:

public int factorial(int input)
{
    if (input == 0 || input == 1)
        return 1;
else
{
    int temp = 1;
    for (int i = 1; i <= input; i++)
        temp = temp * i;
    return temp;
    }
}

但是我发现了一些C ++代码(我真的不知道任何C ++ btw)使用递归循环找到阶乘:

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

有人可以向我解释它是如何工作的吗? 谢谢。

好吧,它利用了一个事实,即factorial(n)n * factorial(n - 1) ,基本情况为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

实现仅使用此递归定义。

让我们逐行分析此内容:

if(number <= 1) return 1;
temp = number * factorial(number - 1);
return temp;

第1行:如果该数字小于或等于零,则返回1。也就是说0! = 1 0! = 11! = 1 1! = 1

第2 + 3行:否则,我们返回number * factorial(number - 1) 让我们看看这个5! (在这里,为了简洁起见,我使用n!作为factorial(n)的同义词)

5!
5 * 4!
5 * 4 * 3!
5 * 4 * 3 * 2!
5 * 4 * 3 * 2 * 1!
5 * 4 * 3 * 3 * 1 // Here we don't have to expand 1! in the same way because of the condition

因此,整个事情扩展了。 它只是使用的属性

n! = n * (n - 1) * ... * 2 * 1 = n * (n - 1)!

警告:与迭代(或尾部递归优化)版本相比,递归代码将一如既往地遭受栈溢出和内存使用量增加的风险,因此使用风险自负。

从语法上讲,C ++代码与用C#编写的相同代码相同。 不要让语言差异让您措手不及! 考虑到变量是在函数顶部声明的,对我来说,它实际上看起来像C。 无论是C ++还是C#,都不是必须的。 我更喜欢在第一次使用变量时声明变量,将声明和初始化结合在一个单独的语句中,但这只是一种样式偏好,不会改变代码的功能。

我将尝试通过在代码段的每一行中添加注释来解释这一点:

// Declare a function named "Factorial" that accepts a single integer parameter,
// and returns an integer value.
int Factorial(int number)
{
    // Declare a temporary variable of type integer
    int temp;

    // This is a guard clause that returns from the function immediately
    // if the value of the argument is less than or equal to 1.
    // In that case, it simply returns a value of 1.
    // (This is important to prevent the function from recursively calling itself
    // forever, producing an infinite loop!)
    if(number <= 1) return 1;

    // Set the value of the temp variable equal to the value of the argument
    // multiplied by a recursive call to the Factorial function
    temp = number * Factorial(number - 1);

    // Return the value of the temporary variable
   return temp;
}

递归调用仅表示该函数从同一函数内部进行调用。 之所以有效,是因为n的阶乘等效于以下语句:

n! = n * (n-1)! 

理解代码工作原理的一种方法是将其添加到测试项目中,然后使用调试器单步执行代码。 Visual Studio在C#应用程序中对此提供了非常丰富的支持。 您可以观察函数如何递归调用自身,观察每一行按顺序执行,甚至可以看到变量的值随对它们执行的操作而变化。

递归函数是在其主体中调用自身的函数。 为使其受限制并最终返回值,必须发生两件事:

  1. 它必须具有一个基本情况,即不再调用自身,返回一个已知值。 此基本情况将停止递归。 对于阶乘函数,当输入为0时,此值为1。

  2. 它的递归应用程序必须收敛到基本情况。 对于阶乘,递归应用程序调用输入减去1的函数,最终将收敛到基本情况。

查看此功能的更简单方法是:(仅对正输入有效):

int factorial(int input) {
  return input == 0 ? 1 : input * factorial(input - 1);
}

递归函数是从同一函数调用的函数

例如:

  Test()
    {
      i++;
      Test();
      cout<<i;
    }

看一下代码,它将一次又一次地调用该函数

递归问题将无限发挥作用,因此希望通过特定条件将其停止

现在上面的代码有一些变化

int i=0; 
Test()
        {
         if(i==10) return;
         i++;
         Test();
         cout<<i;
        }

输出将被10次打印10次,这里cout<<i; 返回后将执行

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM