trie par fusion

trie par fusion - C++ - Programmation

Marsh Posté le 18-11-2002 à 01:31:58    

j'essaye de realiser le trie par fusion mais ce code affiche des valeurs bidons!
pourquoi tout ma pourtant l'air correct?
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define TAILLE 20
  4. void TriFusion(int* t ,int deb,int fin);
  5. void Fusion(int* t,int deb,int fin);
  6. int* RemplirTab(int max);
  7. void print(int* tab)
  8. { int i; for(i=0;i<TAILLE;i++) printf("%d ",tab[i]); }
  9. main()
  10. {
  11.   int* tab;
  12.   int i=0;
  13.  
  14.   tab=RemplirTab(30);
  15.  
  16.   TriFusion(tab,0,TAILLE);
  17.  
  18.   print(tab);
  19. }
  20. void Fusion(int* tab, int deb, int fin)
  21. {
  22.   int milieu=(deb+fin)/2;
  23.   int j,i=0,i1=deb,i2=milieu+1;
  24.   int temp[50];
  25.  
  26.   while(i1<milieu && i2<fin)
  27.     {
  28.       if(tab[i1] < tab[i2])
  29. {
  30.   temp[i]=tab[i1];
  31.   i1++;
  32. }
  33.       else
  34. {
  35.   temp[i]=tab[i2];
  36.   i2++;
  37. }
  38.       i++;
  39.     }
  40.  
  41.   if(i1 < milieu)
  42.     {
  43.       for(j=i1;j<milieu;j++,i++)     
  44.   temp[i]=tab[j];
  45.     }
  46.   else if(i2 < fin)
  47.     {
  48.       for(j=i2;j<fin;j++,i++)
  49.   temp[i]=tab[j];
  50.     }
  51.   for(i=deb;i<fin;i++)
  52.     tab[i]=temp[i];
  53. }
  54. void TriFusion(int* tab, int deb, int fin)
  55. {
  56.   int milieu;
  57.   if(deb<fin)
  58.     {
  59.       milieu=(deb+fin)/2;
  60.       TriFusion(tab,deb,milieu);
  61.       TriFusion(tab,milieu+1,fin);
  62.       Fusion(tab,deb,fin);
  63.     }
  64. }
  65. int* RemplirTab(int max)
  66. {
  67.   int* tab;
  68.   int i;
  69.   tab=(int*)malloc(TAILLE*sizeof(int));
  70.   srand((unsigned)time(NULL));
  71.  
  72.   for(i=0;i<TAILLE;i++)
  73.       tab[i]=rand()%max;   
  74.   return tab;
  75. }


 
les valeurs affichées sont du style '134554347 ... ...'

Reply

Marsh Posté le 18-11-2002 à 01:31:58   

Reply

Marsh Posté le 18-11-2002 à 10:30:28    

les valeurs tordus de ce genre sont en général due à une erreur d'indirection ou d'allocation avec les pointeurs. (g lu le code et j'y comprends rien, mais g souvent des nombres pareils et c du à ca)


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 18-11-2002 à 11:07:25    

salut,
 
j'ai pas la reponse a ta question, par contre prend l'habitude de remplacer tes :
 
(a+b)/2 par (a+b) >> 1 si a et b sont des entiers.
 
Effectivement une division prend de 10 a 30 cycles au microprocesseur et un décalage a droite (qui l'équivalent d'une division par 2) de 1 a 2 cycles (plus les chiffres exactes en tete, mais les ordres de grandeur sont bons)

Reply

Marsh Posté le 18-11-2002 à 11:50:40    

barbarella a écrit a écrit :

par contre prend l'habitude de remplacer tes :
 
(a+b)/2 par (a+b) >> 1 si a et b sont des entiers.




 
Oui, prend l'habitude de faire du code incompréhensible, déjà que le C, c'est facilement le bordel, rajoute en encore.


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 18-11-2002 à 11:56:12    

kadreg a écrit a écrit :

 
 
Oui, prend l'habitude de faire du code incompréhensible, déjà que le C, c'est facilement le bordel, rajoute en encore.




 
:lol:

Reply

Marsh Posté le 18-11-2002 à 12:29:39    

:( snif! toujours pas de réponse à mon pbm

Reply

Marsh Posté le 18-11-2002 à 22:02:42    

barbarella a écrit a écrit :

salut,
j'ai pas la reponse a ta question, par contre prend l'habitude de remplacer tes :
(a+b)/2 par (a+b) >> 1 si a et b sont des entiers.




 
Il faut surtout prendre l'habitude d'optimiser a la fin! Voire laisser soin au compilo de faire ca tout seul.

Reply

Marsh Posté le 18-11-2002 à 22:03:31    

weblook$ a écrit a écrit :

:( snif! toujours pas de réponse à mon pbm  




Je veux bien jeter un oeil a ton code, mais pourrais tu expliquer en quoi ca consiste le tri par fusion? On m'a déja expliqué mais je ne me souviens plus.

Reply

Marsh Posté le 18-11-2002 à 22:33:37    

barbarella a écrit a écrit :

 
(a+b)/2 par (a+b) >> 1 si a et b sont des entiers.




 
Ca c'était valable il y a quelques années. Les compilateurs modernes savent très bien détecter ces genres de cas. D'ailleurs on peut vérifier ca en activant la sortie assembleur de la compilation (sous Visual C++ c'est Project Settings / C++ / Preprocessor / Listing files je crois).
 
Si tu veux optimiser, apprends a connaitre ton compilateur, Luke !

Reply

Marsh Posté le 18-11-2002 à 23:06:50    

Ace17 a écrit a écrit :

 
 
Il faut surtout prendre l'habitude d'optimiser a la fin! Voire laisser soin au compilo de faire ca tout seul.




 
c'est en rien une optimisation, faur arreter cinq minutes. c'est un opérateur.  
 
Faut pas confondre optimisation et utilisation d'operateur.  

Reply

Marsh Posté le 18-11-2002 à 23:06:50   

Reply

Marsh Posté le 18-11-2002 à 23:08:31    

fabsk a écrit a écrit :

 
 
Ca c'était valable il y a quelques années. Les compilateurs modernes savent très bien détecter ces genres de cas. D'ailleurs on peut vérifier ca en activant la sortie assembleur de la compilation (sous Visual C++ c'est Project Settings / C++ / Preprocessor / Listing files je crois).
 
Si tu veux optimiser, apprends a connaitre ton compilateur, Luke !




 
au lieu de donner des leçons, tu devrais essayé de sortir dans le vaste monde, et te rendre compte qu'il n'y pas que VC :D
 
Et c'est quoi cette aggressivité, j'ai donné un conseil, j'ai rien ordonné du tout, alors venez pas le prendre de haut.

Reply

Marsh Posté le 18-11-2002 à 23:41:16    

barbarella a écrit a écrit :

 
il n'y pas que VC :D




 
J'ai essayé sur le gcc que j'ai au bureau (2.7.2, donc putoujeune), il fait aussi l'optimisation lui-même.


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 19-11-2002 à 00:11:06    

Juste une remarque, fais gaffe à tes intervalles. Le standard en C c'est que la borne initialle est incluse mais pas la borne de fin. Donc dans ce cas TriFusion deviens :
 

Code :
  1. void TriFusion(int* tab, int deb, int fin)
  2. {
  3. int milieu;
  4. if(deb<fin-1)
  5.    {
  6.      milieu=(deb+fin)/2;
  7.      TriFusion(tab,deb,milieu);
  8.      TriFusion(tab,milieu,fin);
  9.      Fusion(tab,deb,fin);
  10.    }
  11. }

Reply

Marsh Posté le 19-11-2002 à 00:52:52    

bon j'ai pas réussi à trouver l'erreur, mais je suis à peu prés certain qu'un problème d'adressage est en cause.
 
sinon j'ai réussi à faire ce que je voulais en modifiant le code de     Fusion()
 
Pour les intéréssés:

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. typedef char BOOL;
  5. enum{faux,vrai};
  6. int TAILLE;
  7. void TriFusion(int* t ,int deb,int fin);
  8. void Fusion(int* t,int deb,int fin);
  9. int* RemplirTab(int max);
  10. void Permut(int*,int,int);
  11. void print(int* tab,int m,int s,char* mes);
  12. main(int argc,char **argv)
  13.   if(argc>1)    TAILLE=atoi(argv[1]);
  14.   else      {    exit(0);              }
  15.    
  16.   tab=RemplirTab(30);
  17.   print(tab,0,TAILLE-1,"Tab avant traitement: " );
  18.   TriFusion(tab,0,TAILLE-1);
  19.   print(tab,0,TAILLE-1,"Tab aprés traitement: " );
  20. }
  21. void Fusion(int* tab,int deb,int fin)
  22. {
  23.   BOOL continuer;
  24.   int mid=(deb+fin)/2;
  25.   int j,i=mid+1;
  26.   while(i<=fin)
  27.   {
  28.       j=0;
  29.       continuer=vrai;
  30.       while(j<i && continuer)
  31.       {
  32. if( tab[i-j-1] > tab[i-j] )
  33.   Permut(tab,i-j-1,i-j);
  34. else
  35.   continuer=faux;
  36. j++;
  37.       }
  38.       i++;
  39.   }
  40. }
  41. void TriFusion(int* tab, int deb, int fin)
  42. {
  43.   int milieu;
  44.   if(deb<fin)
  45.     {
  46.        milieu=(deb+fin)/2;
  47.      
  48.        if(milieu>deb)
  49.  TriFusion(tab,deb,milieu);
  50.      
  51.        if(milieu+1<fin)
  52.  TriFusion(tab,milieu+1,fin);
  53.      
  54.        Fusion(tab,deb,fin); 
  55.     }
  56. }
  57. void Permut(int* tab,int a,int b)
  58. {
  59.   int temp;
  60.   temp=tab[a];
  61.   tab[a]=tab[b];
  62.   tab[b]=temp;
  63. }
  64. int* RemplirTab(int max)
  65. {
  66.   int* tab;
  67.   int i;
  68.   tab=(int*)malloc(TAILLE*sizeof(int));
  69.   srand((unsigned)time(NULL));
  70.  
  71.   for(i=0;i<TAILLE;i++)
  72.       tab[i]=rand()%(max+1);   
  73.   return tab;
  74. }
  75. void print(int* tab,int m,int s,char* mes)
  76. {
  77.   int i;
  78.   if(strlen(mes)>0)
  79.     printf("%s",mes);
  80.   for(i=m;i<=s;i++)
  81.     printf("%d ",tab[i]);
  82.  
  83.   putchar('\n');
  84. }


Message édité par weblook$ le 19-11-2002 à 00:54:48
Reply

Marsh Posté le 19-11-2002 à 04:16:37    

L'erreur ne viendrait pas du fait que comme il ne respecte pas l'intervalle de son tableau (il faut mettre TriFusion(tab,0,TAILLE-1) dans ton main), il va dans trifusion chercher des valeurs dans des zones memoires bidon et donc du coup va les rapatrier dans son tableau tout beau?


Message édité par Angel_Dooglas le 19-11-2002 à 04:22:12
Reply

Marsh Posté le 19-11-2002 à 04:17:59    

Code :
  1. TriFusion(tab,0,TAILLE); //très probablement TAILLE-1
  2. int temp[50]; //je m'étonne d'une taille fixe...
  3. //ceci...
  4. while(i1<milieu && i2<fin)
  5. {
  6. if(tab[i1] < tab[i2])
  7. {
  8.  temp[i]=tab[i1];
  9.  i1++;
  10. }
  11. else
  12. {
  13.  temp[i]=tab[i2];
  14.  i2++;
  15. }
  16. i++;
  17. }
  18. //...peut s'écrire comme ça.
  19. for(i= 0 ; i1<milieu && i2<fin ; ++i){
  20. int* pi= (tab[i1] < tab[i2]) ? &i1 : &i2 ;
  21. temp[i]= tab[*pi];
  22. (*pi)++;
  23. }


 
J'ai eu la flemme de vérifier l'alorithme... désolé.
 

Citation :

(a+b)/2 par (a+b) >> 1 si a et b sont des entiers.

A condition que ce soient (1)des entiers (2)positifs représentés en (3)base 2 en (4)numération arabe.
 
Il faut coder l'opération qu'on veut faire, et laisser au compilateur ce genre d'optimisation.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 19-11-2002 à 06:58:33    

barbarella a écrit a écrit :

salut,
 
j'ai pas la reponse a ta question, par contre prend l'habitude de remplacer tes :
 
(a+b)/2 par (a+b) >> 1 si a et b sont des entiers.
 
Effectivement une division prend de 10 a 30 cycles au microprocesseur et un décalage a droite (qui l'équivalent d'une division par 2) de 1 a 2 cycles (plus les chiffres exactes en tete, mais les ordres de grandeur sont bons)  




 
Le compilateur fait ca vraiment tres bien tout seul tu sais.
 
Remplacer /2 par >>1 , n'importe quel compilo bidon peux le faire.
 
Par contre, si tu veux produire du code incomprehensible, oui, fais comme ca.
 


---------------
L'ingénieur chipset nortiaux : Une iFricandelle svp ! "Spa du pâté, hin!" ©®Janfynette | "La plus grosse collec vivante de bans abusifs sur pattes" | OCCT v12 OUT !
Reply

Marsh Posté le 19-11-2002 à 09:44:00    

Ai déja essayé mesurer différences de rapidité avec BC 3 sous Windows 3.11 sur mon 486/100MHz, car on voit mieux au chrono :D.
 
Multipl/divis par 2^n ou décalages, pas vu la moindre différence de rapidité. J'ai donc opté pour lecture facile.

Reply

Marsh Posté le 20-11-2002 à 23:56:28    

ouf enfin c'est trouvé  :)
c'était tout simplement des erreurs d'indice dans la fonction Fusion :sarcastic:

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed