UVa 3n + 1案例递归堆栈溢出

时间:2010-08-11 07:05:37

标签: c recursion

我试图解决这个第一个挑战,但我陷入困境, 我喜欢快速程序,所以我决定使用递归方法而不是迭代

不幸的是,当输入是一个大整数(100000>输入> 1000000)时,它经常崩溃

所以我调试它,它显示堆栈溢出错误

请帮助我,我不知道该怎么做,香港专业教育学院尝试将数据类型更改为无符号长整数,无符号整数等,但没有一个工作

这是我的代码, 即时通讯使用ANSI C

#include "stdio.h"

int cek(int n) {
    return n % 2;
}

int fung(int n,int c) {
    if (n == 1) {
        return c;
    }
    if (!cek(n)) {
        return fung(n/2,++c);
    }
    else {
        return fung((n*3)+1,++c);
    }
}

int comp(int i,int j,int tmp) {
    int temp;
    if (i == j)
        return tmp;
    temp = fung(i,1);
    if (temp > tmp)
        return comp(++i,j,temp);
    else
        return comp(++i,j,tmp);
}

int main() {
    int i,j,tmp;
    while (scanf("%d %d",&i,&j)) {
        if (i > j) {
            tmp = i;
            i = j;
            j = tmp;
        }
        printf("%d %d %d\n",i,j,comp(i,j,0));
    }
    return 0;
}

PS:对不起我的愚蠢,我真是个新手@ _ @

3 个答案:

答案 0 :(得分:6)

递归不可能比迭代更快,实际上它可能会更慢。

调用堆栈的大小有限,如果你的递归比这更深,那么你无能为力。特别是在Collat​​z问题中,没有办法告诉你需要多少步骤。改为使用迭代方法重写它。

(如果您的编译器执行尾调用优化,递归可能仍然有效。但标准不要求TCO,因此它将导致不可移植的代码。显然,您的编译器无论如何都不会优化此特定的尾调用。)< / p>

答案 1 :(得分:2)

不是C专家,但通常编译器强制执行调用堆栈深度限制。您可以使用编译器标志更改此设置,但这不会解决您的问题。使算法迭代而不是递归将解决它。

递归算法通常不会比迭代算法快。但他们通常更容易理解。 (=更优雅)

答案 2 :(得分:-1)

好的,伙计们, 我找到了!!!

所以这是我的代码,我仍然使用递归但仅用于内部循环fung(),

我没有真正留下深刻的印象,因为它需要0.5秒来计算输入1和1000000,某人的代码可以在0秒内完成,LOL

我用迭代方法改变外循环comp(),

看这里

#include "stdio.h"
/*#include "windows.h"*/

int cek(int n) {
    return n % 2;
}

unsigned int fung(unsigned int n,unsigned int c) {
    if (n == 1) return c;
    if (!cek(n)) return fung(n/2,++c);
    else return fung((n*3)+1,++c);
}

/*
Above recursion will looked like this in iterative method
int func(int n) {
    int c=1;
    while (n != 1) {
        c++;
        if (n % 2 == 0)
            n=n/2;
        else
            n=(n*3)+1;
    }
    return c;
}
*/

/*Outer Loop*/
int iter(int i,int j) {
    int tmp1=0,tmp2;
    while (i <= j) {
        tmp2 = fung(i,1);
        if (tmp1 < tmp2)
            tmp1 = tmp2;
        i++;
    }
    return tmp1;
}

int main() {
    unsigned int i,j,s,f;
    while (scanf("%d %d",&i,&j)) {            /*UVa Standard, infinite loop*/
        /*s = GetTickCount();*/
        printf("%d %d %d",i,j,iter(i,j));
        /*f = GetTickCount();
        printf("%lu\n",f-s);*/
    }
    return 0;
}