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

发布于 2024-09-14 00:25:21 字数 963 浏览 4 评论 0原文

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

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

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

请帮助我 都不起作用

,我不知道该怎么办,我尝试将数据类型更改为 unsigned long、unsigned int 等,但我的代码在这里 , 我使用 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:抱歉我的愚蠢,我真的是一个新手@_@

im trying to solve this very first challange but i get stuck,
i like fast program, so i decided to use recursive method not iteration

unfortunately, when the input is a big integer (100000 > input > 1000000), its often crash

so i debug it, and it shows stack overflow error

please help me, i dont know what to do, ive tried to change data type to unsigned long, unsigned int, etc, but none of it works

here is my code,
im using 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: sorry for my stupidness, im really a newbie @_@

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风吹过旳痕迹 2024-09-21 00:25:22

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

调用堆栈的大小是有限的,如果您的递归比这更深,您将无能为力。特别是在 Collat​​z 问题中,无法预先知道您需要多少步。使用迭代方法重写它。

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

Recursion is not likely to be faster than iteration, and in fact it's likely to be slower.

The call stack has a limited size, and if your recursion goes deeper than that, there's nothing you can do about it. Especially in the Collatz problem, there's no way to tell up front how many steps you'll need. Rewrite this using an iterative method instead.

(If your compiler does tail call optimization, recursion might still work. But TCO is not required by the standard, so it will lead to unportable code. And apparently, your compiler does not optimize this particular tail call anyway.)

萌逼全场 2024-09-21 00:25:22

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

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

Not a C expert, but usually there is a call stack depth limit enforced by the compiler. Probably you can change this with a compiler flag, but this will not solve your problem. Making the algorithm iterative instead of recursive will fix it.

Recursive algorithms won't go faster than iterative ones, usually. But they are typically nicer to understand. (= more elegant)

无风消散 2024-09-21 00:25:22

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

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

我对它印象不深,因为它需要 0,5 秒来计算输入 1 和 1000000,有人的代码可以在 0 秒内完成,哈哈,

我用迭代方法改变了外循环 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;
}

Okay guys,
i found it!!!

so this is my code, i still use recursion but only for the inner loop fung(),

im not really impressed of it, because its need 0,5 sec to count input 1 and 1000000, someone's code outhere can do it in 0 sec, LOL

i change the outer loop comp() with iterative method,

look here

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文