当前位置: 首页 > 知识库问答 >
问题:

递归函数是否有一些限制?例如:函数需要多少层?

邢硕
2023-03-14

制作了一个递归函数,给出了给定起始数的collatz序列中有多少项,这是代码n=13,例如:

int collatz(long n,long o)
{
    if (n!=1) {
        if(n%2==0)
            return collatz(n/2,o+1);
        else
            return collatz((n*3)+1,o+1);
    } else
        printf("%ld\t",o);
}
void main()
{
    collatz(13,0);
}

功能按预期运行;然而,对于一些整数,例如“n=113383”,有些东西溢出(我猜)并返回:

Process returned -1073741571 (0xC00000FD)   execution time : 4.631 s
Press any key to continue.

请原谅我的非技术性解释,非常感谢!

共有2个答案

屠瑞
2023-03-14

这里发生的是堆栈溢出。这是因为函数的每次调用都会创建一个新的堆栈帧,如果堆栈帧太多,堆栈的内存就会耗尽。您可以通过使用迭代而不是递归来修复它。

此外,long可能无法保存collatz序列为起始值113383生成的数字(我在MSVC中没有)。改为使用long-long,即至少64位大。总而言之,它可能是这样的:

void collatz(long long n)
{
    long o;
    for (o = 0; n > 1; o++) {
        if (n % 2 == 0)
            n /= 2;
        else
            n = n * 3 + 1;
    }
    printf("%ld\t", o);
    return;
}

int main()
{
    collatz(113383);
    return 0;
}

请注意,我们现在有一个for循环,而不是递归。

易昌翰
2023-03-14

C标准本身对递归深度没有限制。您可能会导致堆栈溢出,但堆栈大小在不同的环境中是不同的。我认为Windows有1MB,Linux有8MB。它还取决于函数堆栈帧的大小,而堆栈帧的大小又取决于它有多少个变量和类型。

在本例中,您有两个长变量,每个变量可能是8个字节。您还有一个字符串,它是5个字节,可能会在堆栈中结束,但我不确定。除此之外,还有两个指向函数返回地址和前一个堆栈帧的指针的开销,在64位html" target="_blank">系统上每个指针是8个字节。因此,函数的堆栈帧大约是32字节左右。也许再多一点。因此,在Linux系统上,我猜您的函数将在大约200000的深度崩溃。

如果这是一个问题,请考虑将函数重写为非递归变量。看看Blaze的答案,了解如何为您的案例做到这一点。正如andreee在下面评论的那样:

附加说明:您可以在Linux下使用ulimit-s增加堆栈大小(也可以使用ulimit-s unlimited),在MSVC中,您可以设置/F编译标志来增加程序的堆栈大小。有关MinGW,请参阅本文。

 类似资料:
  • 问题 你想在一个函数中调用相同的函数。 解决方案 使用一个命名函数: ping = -> console.log "Pinged" setTimeout ping, 1000 若为未命名函数,则使用 @arguments.callee@: delay = 1000 setTimeout((-> console.log "Pinged" setTimeout arg

  • 在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。 举个例子,我们来计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出: fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n 所以,fact(n)可以表示为n x fact(n-1),

  • 在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。 举个例子,我们来计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示,可以看出: fact(n)=n!=1\times2\times3\times\cdot\cdot\cdot\times(n-1)\times n=(n-1)!\times n=fact(n-1)\times n

  • 来自Python的递归追加列表函数,试图递归地获取与文件结构相关的权限列表。 另一种情况是,A=允许,R=限制 输出将是[True,True,False,False,True,True,True]

  • 我在程序的某个部分遇到了问题,我将一个充当lambda函数的对象传递给另一个函数(我需要捕获一个常量this指针,这样我就不能使用实际的lambda)。这导致调用lambda的copy构造函数,该构造函数再次调用copy构造函数,最终堆栈溢出。我知道发生了什么,但我不知道复制构造函数为什么调用自己,也不知道如何解决这个问题。我复制了下面的问题。 编译器:MSVC 2010

  • 我还不太理解递归,我有一些作业我不能解决。有人有主意吗? 任务1:实现一个int方法max(int[]arr,int i),该方法返回arr中所有元素的最大值和索引 这是我迄今为止的代码: 实际上它是有效的,但它的风格很差,所以我的问题是:如果没有私有静态int max,我如何实现递归方法?我不允许向该方法添加第三个参数。 任务2:实现一个布尔方法包含值(int[]arr,int val),如果a