如何更改代码,创建递归函数

时间:2019-07-16 15:24:51

标签: c function recursion cs50

我参加了名为CS50的课程。我最近一直在学习递归函数,尽管我创建了一个名为Collat​​z的程序,该程序可以实现我想要的功能,但它内部没有递归函数,因为该函数不会自行调用。我被困住了,我不知道该如何实现一个递归函数,以使其看起来整洁干净并可以自我调用。

我试图在我的主要功能旁边实现一个功能。但是我不知道该函数的外观,以及它如何调用自身。

//int x(int n);

int main(void)
{
    int n;
    //j is a counter for the number of times 'n' has to be calculated to get n==1
    int j = 0;

    //Ask for an integer
    printf("Int: ");
    scanf("%i", &n);

    //Check for 0 or less
    if (n <= 0)
    {
        printf("ERROR.")
        return 1;
    }

    //This is where recursion should be implemented
    while (n != 1)
    {
        if (n % 2 != 0)
        {
            while ((n % 2) != 0)
            {
                n = 3*n + 1 ;
                j++;
            }
        }
        else if ((n % 2) == 0)
        {
            while (n != 1)
            {
                n /= 2;
                j++;
            }
        }
    }
    printf("N: %i, number of times: %i \n", n,j);
}

/*
int x(int n)
{
    Should a recursive function be implemented here?
}
*/

输出正常。 输出应为数字n,该数字应始终为1,以便证明程序正常运行并始终获得数字1,以及从n获得数字1所需的步数。

3 个答案:

答案 0 :(得分:2)

您在这里。:)

#include <stdio.h>

unsigned int collatz( unsigned int n )
{
    return n < 2 ? 0 : 1 + collatz( n % 2 == 0 ? n / 2 : 3 * n + 1 );
}

int main(void) 
{
    while ( 1 )
    {
        unsigned int n;

        printf( "Enter a non-negative number (0 - exit): " );

        if ( scanf( "%u", &n ) != 1 || n == 0 ) break;

        printf( "The number of steps is %u\n\n", collatz( n ) );
    }

    return 0;
}

程序输出看起来像

Enter a non-negative number (0 - exit): 19
The number of steps is 20

Enter a non-negative number (0 - exit): 0

答案 1 :(得分:0)

对于像这样的事情,我建议您使用一个递归函数,该函数返回使n等于1所花费的时间数,因为这实际上是您要跟踪的全部。由于您要递归执行的代码是一个循环,因此相对容易找到基本情况(或退出条件)。在这种情况下,将是n == 1的时候。所以这导致我们拥有类似这样的东西

int recursive_function(int n) {
    if (n == 1) {
        return 0;
    }
}

现在,我们需要关注逻辑,以便跟踪函数运行的次数(本质上是j),我们应该使函数返回其运行的次数,然后将其设为更容易跟踪。因此,为此,我们将向函数添加另一个return语句,并使其再次运行,因为我们已经设置了退出条件来告诉我们何时停止。之后,您只需要添加逻辑即可,但最终应该是这样的:

int recursive_function(int n) {
    if (n == 1) {
        return 0;
    } else if (n % 2 != 0 ) {
        n = 3 * n + 1 ;
    } else if (n % 2 == 0) {
        n /= 2;
    }
    return 1 + recursive_function(n);
}

答案 2 :(得分:0)

好吧,由于您不知道递归函数的外观或应如何调用,因此下面是一个简单的示例。

int fact(int n)
{
  if (n == 0) // this is the stopping case
    return 1;
  else
    return n * fact(n-1)); // this is what makes the function recursive
}

在此示例中,我们正在计算数字的阶乘。我们需要有一个分支,以便当我们知道何时应该停止调用该函数时。从根本上讲,此递归函数如下:

for (int i = 0; i < n; i ++)
{
  result = result * i;
}

具有递归功能意味着它摆脱了循环。我鼓励您从最外层​​的while循环开始,并确定如何通过在代码的各个部分中实现一些返回函数以使其递归来消除这种情况。作为提示,您似乎应该具有以下if语句:

if (n != 1)
  return /* whatever is fit for your stopping case, should be an integer */

递归函数要注意的另一重要事项-在调用函数本身时,输入需要更改。我的意思是,您不应该具有这样的功能:

int x(int n)
{
  if (n == 0)
    return 1;
  else
    return x(n);
}

输入相同的数字并且没有类似return x(n-1)的内容将创建一个无限循环,因为除非输入的原始数字达到停止情况,否则无法达到停止状态。

当然,您还可以在递归调用中添加更多计算,并编写类似return 7 * x(n) / 2;的内容。很多初学者在学习递归函数时常常会忘记这一点,只想为自己的return语句写return x(n-2);之类的东西。

在您的情况下,看起来“停止情况”应该为if (n == 1)

希望这足以让您入门!