简体   繁体   English

为什么在计算Pascal三角形的元素时在递归C程序中出现堆栈溢出错误?

[英]Why am I getting Stack Overflow error in Recursive C program while computing elements of pascal triangle?

I am writing a C program to compute (i,j)th element in Pascular Triangle ie f(n,1) = f(n,n) = n, and f(n,k) = f(n-1,k) + f(n-1,k-1) for 1 < k < n I need to print value modulo 1000000007. The Code follows : 我正在编写一个C程序来计算Pascular Triangle中的第(i,j)个元素,即f(n,1)= f(n,n)= n,而f(n,k)= f(n-1,k )+ f(n-1,k-1)表示1 <k <n我需要以1000000007为模输出值。代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

unsigned long int returnModPascal(unsigned long int n,unsigned long int k);

int main()
{
    int t;
    unsigned long int ans,n,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lu %lu",&n,&k);
        ans=returnModPascal(n,k);
        printf("%lu",ans);
    }

    return 0;
}

unsigned long int returnModPascal(unsigned long int n,unsigned long int k)
{
    unsigned long int tempans,tempans1,tempans2;
    if(k==1 || k==n)
        tempans=n;
    else
    {
        tempans1=returnModPascal(n-1,k);
        if (tempans1>=1000000007)
            tempans1=tempans1%1000000007;
        tempans2=returnModPascal(n-1,k-1);
        if (tempans2>=1000000007)
            tempans2=tempans2%1000000007;
        if (tempans1+tempans2>=1000000007)
            tempans=tempans1+tempans2-1000000007;
        else
            tempans=tempans1+tempans2;
    }

    return tempans;
}

When i give input for example 123456 3 as n & k ( It works fine with smaller integer values like 23 2 or 12 3 as n&k ) Error is coming 当我以n&k的形式输入123456 3时( 对于较小的整数值(如23 2或12 3的 n&k, 它可以正常工作 )出现错误

Unhandled exception at 0x003C3D79 in DummyProject.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x003D2F70). DummyProject.exe中0x003C3D79的未处理异常:0xC00000FD:堆栈溢出(参数:0x00000001,0x003D2F70)。

Any Help is appreciated. 任何帮助表示赞赏。

Since you made your returnModPascal function recursive, there must be space on the stack for each recursive call. 由于您使returnModPascal函数具有递归性,因此每个递归调用的堆栈上都必须有空间。

For example, if you read in 123456 , your call to returnModPascal will end up allocating a stack frame for n = 123456 , n = 123455 , n = 123454 , and so on. 例如,如果您读入123456 ,则对returnModPascal的调用最终将为n = 123456n = 123455n = 123454分配一个堆栈帧。 There's not nearly enough memory for that. 没有足够的存储空间。

To fix this, you're going to have to rewrite your function so that you don't end up making this many recursive calls for the larger inputs. 要解决此问题,您将不得不重写函数,以免最终对较大的输入进行如此众多的递归调用。

The typical stack limits are in some 1000s of KBs. 典型的堆栈限制约为1000 KB。 In linux you can use 在Linux中,您可以使用

ulimit -a

to know yours (mine is about 8 MB). 知道你的(我的大约8 MB)。 Since unsigned long int can go up to (again, assuming gcc) 18446744073709551615 (in 64 bit) or 4294967295 (in 32 bit) [I maybe wrong, See your limits.h], and your one stack frame must be of size 2 words, a stack overflow is quite imminent. 由于unsigned long int可以升至(再次假定为gcc)18446744073709551615(64位)或4294967295(32位)[我可能错了,请参见您的limits.h],并且一个堆栈帧的大小必须为2个字,堆栈溢出迫在眉睫。

Edit: I see you want an alternative. 编辑:我看到你想要一个替代方案。 Have you considered using combinatorics? 您是否考虑过使用组合数学? "Calculate" (i,j)th entry by i C j . i C j “计算”第(i,j)个条目。 By that I mean don't actually find factorials and multiply, but cancel out all the terms you can (integral value will always appear) until only a sequence of integers (mathematical sense) remain. 我的意思是说,实际上并没有找到阶乘并乘法,而是取消了所有可能的项(积分值将始终出现),直到只剩下整数序列(数学意义上)为止。 Use modular multiplication (mod 1000000007). 使用模乘(mod 1000000007)。 Read up about efficient modular multiplication using generator exponents. 阅读有关使用生成器指数的高效模块化乘法的信息。

Look at this line of code: 查看以下代码行:

tempans1=returnModPascal(n-1,k);

You call the recursive function at the very beginning, this means that the function will go till the very end of recursion chain before it gets any chance to further process the input. 您从一开始就调用递归函数,这意味着该函数将一直运行到递归链的最末端,然后才有机会进一步处理输入。 So if you call this function with a comparatively large input such as 123456 , this means that the function will have to "stacked" 12345 times before it finally gets to evaluate the if condition. 因此,如果使用相对较大的输入(例如123456调用此函数,则意味着该函数将必须“堆叠” 12345次,才能最终评估if条件。

You should try reducing the input, or a better alternative is to call the function recursively after if statement. 您应该尝试减少输入,或者更好的选择是在if语句之后递归调用函数。

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

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