2010-08-11 8 views
2

im essayant de résoudre ce premier challange mais je coincé, j'aime programme rapide, donc je décidé d'utiliser la méthode récursive pas itérationUVa 3n + 1 cas récursif Stack Overflow

malheureusement, lorsque l'entrée est grand entier (100000> entrée> 1000000), son s'écraser souvent

donc je déboguer, et il indique l'erreur de débordement de pile

s'il vous plaît aidez-moi, je ne sais pas quoi faire, ive essayé de changer le type de données non signé long, int non signé, etc, mais rien ne fonctionne

ici est mon code, im utilisant 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: désolé pour mon stupidité, im vraiment un débutant @ _ @

+3

« i like programme rapide, donc je décidé d'utiliser rec méthode ursive et non itération "- Qui vous a enseigné cela? En outre, vous devriez essayer de préférer le programme _readable_ aux programmes _fast_. – polygenelubricants

+0

Voir 'temp' et' tmp' utilisés pour le même paramètre dans la même fonction me fait mal aux yeux. – Blindy

+0

S'il vous plaît commenter votre code et décrire ce qu'il est censé faire, vous pouvez le faire en éditant votre question. Si vous avez des hypothèses cachées sur les valeurs, mettez des assertions pour vous assurer qu'elles sont vraies. Également indiquer plus précisément pour quelles entrées il fonctionne, pour lequel pas etc. –

Répondre

2

pas un expert en C, mais en général il y a une pile d'appel limite de profondeur imposée par le compilateur. Probablement vous pouvez changer cela avec un drapeau de compilateur, mais cela ne résoudra pas votre problème. Rendre l'algorithme itératif au lieu de récursif le corrigera.

Les algorithmes récursifs ne vont pas plus vite que les itératifs, habituellement. Mais ils sont généralement plus agréables à comprendre. (= plus élégant)

+2

Ce problème est plus élégamment exprimé comme une simple boucle, plutôt que d'une fonction récursive, à mon humble avis. – Thomas

6

La récursion ne devrait pas être plus rapide que l'itération, et en fait, elle sera probablement plus lente. La pile d'appel a une taille limitée, et si votre récursion est plus profonde, vous ne pouvez rien y faire. Surtout dans le problème de Collatz, il n'y a aucun moyen de dire à l'avance combien de pas vous aurez besoin. Réécrivez ceci en utilisant une méthode itérative à la place.

(Si votre compilateur effectue l'optimisation des appels de queue, la récursivité peut toujours fonctionner, mais TCO n'est pas requis par le standard, donc il conduira au code non-portable.) Et apparemment, votre compilateur n'optimise pas cet appel.

+0

Il se peut qu'il n'ait pas activé les optimisations (pour TCE). En fait, c'est une pensée effrayante! – leppie

+0

Merci pour vos informations, mais Outhere j'ai vu même code récursif, mais en C++ il fonctionne très bien, pas comme moi thats pourquoi im vraiment frustated = _ = ici le code cycle de unsigned int (unsigned int CurValue , nombre entier non signé) { if (curValue == 1) nombre de retour; si (isEven (curValue)) cycle de retour (curValue/2, nombre + 1); autre cycle de retour ((curValue * 3) +1, compte + 1); } – Ady

+0

ahh, ne peut pas utiliser le code tag dans le commentaire lol @ _ @ – Ady

-1

Bon les gars, je l'ai trouvé !!!

donc c'est mon code, je l'utilise encore récursion mais seulement pour la fung boucle intérieure(),

je ne suis pas vraiment impressionné de celui-ci, parce que son besoin de 0,5 s à compter entrée 1 et 1000000, quelqu'un Code Outhere peut le faire en 0 sec, LOL

i changer la maquette en boucle externe() avec la méthode itérative,

regarder ici

#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; 
} 
+0

Veuillez mettre à jour votre question, au lieu d'y répondre vous-même. – Vatine

Questions connexes