std::list liste.sort();

std::list liste.sort(); - C++ - Programmation

Marsh Posté le 25-11-2002 à 21:24:40    

Bonsoir,
 
j'ai declaré une liste a partir de la STL. C'est une liste du type d'une classe.
 
===> list<NomDeClasse> liste;
 
j'aimerais faire un sort de cette liste grace a la methode sort fournie dans la class list de c++ builder.
 
Comment faire pour que la liste soit trié suivant un champ (string) se trouvant dans ma classe.
 
On m'a dit qu'il fallait surcharger l'operateur < mais je vois pas comment faire !!!
 
Merci de m'aider.
 
Bonne soirée

Reply

Marsh Posté le 25-11-2002 à 21:24:40   

Reply

Marsh Posté le 25-11-2002 à 21:34:22    

Tu peux definir:
 

Code :
  1. struct MyGreater {
  2.   bool operator() (const NomDeClasse &c1, const NomDeClasse &c2)
  3.   {
  4.      return c1.champ > c2.champ;
  5.   };
  6. }


 
puis
 

Code :
  1. liste.sort(MyGreater());


 
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 25-11-2002 à 21:37:40    

merci beaucoup

Reply

Marsh Posté le 25-11-2002 à 21:42:19    

Et pour que ce soit dans l'ordre inverse
tu remplaces MyGreater par la fonction inverse :)
 
A+
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 25-11-2002 à 21:45:06    

y a pas de methode std::list::sort dans STL confond pas tout.
 
utilises std::sort
 
edit: honte à mwa  [:totoz]


Message édité par Taz@PPC le 25-11-2002 à 22:18:09

---------------
du bon usage de rand [C] / [C++]
Reply

Marsh Posté le 25-11-2002 à 21:46:31    

Taz@PPC a écrit a écrit :

y a pas de methode std::list::sort dans STL confond pas tout.
 
utilises std::sort




 
ca va toi??
 
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 25-11-2002 à 21:53:43    

:hello:  :sol:


---------------
du bon usage de rand [C] / [C++]
Reply

Marsh Posté le 25-11-2002 à 21:55:18    

Taz@PPC a écrit a écrit :

y a pas de methode std::list::sort dans STL confond pas tout.
 
utilises std::sort




 
tu ne peux pas utiliser sort d'algorithm  
sur des listes mais tu devais surement savoir ca..
 
LeGreg


---------------
voxel terrain render engine | animation mentor
Reply

Marsh Posté le 25-11-2002 à 22:08:32    

legreg a écrit a écrit :

 
 
tu ne peux pas utiliser sort d'algorithm  
sur des listes mais tu devais surement savoir ca..
 
LeGreg




 
oui je me suis mal exprimé et c'est vrai que j'ai pas les yeux en face des trous apres 7 parties de War3 d'affilées ( :pt1cable: ).
 
y a bien une std::list<T>::sort() et une std::list<T>::sort(Predicat)
 
std::list<T>::sort() <=> std::list<T>::sort(std::less<T>())
 
comme chacun sait on ne peut utiliser std::sort sur une std::list car std::sort a besoin de RandomAccessIterator que ne peut fournir une std::list


---------------
du bon usage de rand [C] / [C++]
Reply

Marsh Posté le 26-11-2002 à 21:23:00    

Taz@PPC a écrit a écrit :

 
oui je me suis mal exprimé et c'est vrai que j'ai pas les yeux en face des trous apres 7 parties de War3 d'affilées ( :pt1cable: ).




Tu t'es planté, c'est tout  :D

Reply

Marsh Posté le 26-11-2002 à 21:23:00   

Reply

Marsh Posté le 26-11-2002 à 21:41:29    

fabsk a écrit a écrit :

 
Tu t'es planté, c'est tout  :D  




 
 
moi au moins j'explique  :sarcastic:  :D  :p


---------------
du bon usage de rand [C] / [C++]
Reply

Marsh Posté le 21-10-2009 à 17:54:08    

Salut, dsl de détérer le sujet mais j'ai un problème très semblable. Impossible de faire fonctionner mon opérateur sort :
 

Code :
  1. class Noeud
  2. {
  3. public:
  4. string libelle;
  5. list<Noeud *> fils;
  6. bool Noeud::operator<(const Noeud &N) //retourne vrai si le libelle de moi meme est situé avant le libellé de N
  7. {
  8.  return libelle < N.libelle;
  9.              }
  10. ...


 
lorsque j'utilise sort sur ma list<Noeud *>,il ne se passe rien.
 
Quelqu'un pourrait me dire ce que j'ai louper ?
merci


Message édité par espagnol49 le 21-10-2009 à 17:54:44
Reply

Marsh Posté le 21-10-2009 à 18:29:12    

Comment ca, il ne se passe rien ? Il trie selon tes pointeurs, comme tu le lui demandes très probablement.


---------------
last.fm
Reply

Marsh Posté le 22-10-2009 à 00:29:52    

il se passe rien, en effet ce n'est pas très clair.
 
j'ai une list<Noeud *> que je remplis (avec les libelle dans un desordre alphabetique)
j'affiche ma liste -> tout est Ok elle est dans le desordre (ordre dans lequel je l'ai rentré)
je la sort puis la ré affiche -> l'ordre est toujours le meme
 
d'ou le il ne se passe rien.
 
Je poste l'exemple complet demain matin, parce que la ca doit manquer d'info utile pour vraiment voir le probleme.
 
a demain

Reply

Marsh Posté le 22-10-2009 à 08:47:26    

Une liste de pointeurs sera triee avec l'ordre definis sur les pointeurs, pas sur les objets pointes si tu ne specifies pas explicitement la fonction de comparaisons a utiliser.


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 22-10-2009 à 10:37:15    

Code :
  1. class Noeud
  2. {
  3. public:
  4. string libelle;
  5. list<Noeud *> fils;
  6. bool operator< (const Noeud *c1)
  7. {
  8.  return libelle < c1->libelle;
  9. }
  10. Noeud(string texte)
  11. {
  12.  libelle=texte;
  13. }
  14. void ajouterFils(string texte)
  15. {
  16.  Noeud* nouveauNoeud = new Noeud(texte);
  17.  fils.push_front(nouveauNoeud);
  18. }
  19. void afficher(int NbTab)
  20. {
  21.  if (!fils.empty())
  22.  {
  23.   fils.sort();
  24.   insererTab(NbTab);
  25.   cout<<libelle<<endl;
  26.   list<Noeud*>::iterator it;
  27.   for (it=fils.begin(); it!=fils.end(); ++it)
  28.   {
  29.    (*it)->afficher(NbTab+1);
  30.   }
  31.  }
  32.  else
  33.  {
  34.   insererTab(NbTab);
  35.   cout<<libelle<<endl;
  36.  }
  37. }
  38. };
  39. int main(void)
  40. {
  41. Noeud* niveau1=new Noeud("Niveau1" );
  42. Noeud* niveau4=new Noeud("Niveau4" );
  43. niveau1->ajouterFils("Niveau20" );
  44. niveau1->ajouterFils("Niveau22" );
  45. niveau1->ajouterFils("Niveau23" );
  46. niveau1->ajouterFils("Niveau21" );
  47. niveau1->fils.front()->ajouterFils("test2" );
  48. niveau1->fils.front()->ajouterFils("test1" );
  49. niveau1->fils.front()->ajouterFils("test3" );
  50. niveau1->afficher(0);
  51. niveau1->fils.sort();
  52. niveau1->afficher(0);
  53. return 0;
  54. }


 
Voila le retour dans la console :
 

Code :
  1. Niveau1
  2.         Niveau20
  3.         Niveau22
  4.         Niveau23
  5.         Niveau21
  6.                 test2
  7.                 test1
  8.                 test3
  9. Niveau1
  10.         Niveau20
  11.         Niveau22
  12.         Niveau23
  13.         Niveau21
  14.                 test2
  15.                 test1
  16.                 test3
  17. Press any key to continue


---------------
----------------------------------------
Reply

Marsh Posté le 22-10-2009 à 10:42:11    

des new et jamais de delete ... et on t'a déjà donné deux fois la raison du comportement que tu as, cf les deux posts qui précèdent le tien :)


---------------
last.fm
Reply

Marsh Posté le 22-10-2009 à 10:51:56    

Un Programmeur a écrit :

Une liste de pointeurs sera triee avec l'ordre definis sur les pointeurs, pas sur les objets pointes si tu ne specifies pas explicitement la fonction de comparaisons a utiliser.


 
Comment je peux spécifier cette fonction pour trier ma liste à mon gout ?


---------------
----------------------------------------
Reply

Marsh Posté le 22-10-2009 à 10:55:05    

tu peux appeler sort en lui passant en argument un prédicat, c'est ce prédicat qui fera la comparaison comme tu le souhaites entre les noeuds
 
Edit, juste pour te mâcher le travail au cas où mon explication ne serait pas assez claire :

Code :
  1. bool pred( const Noeud *l, const Noeud *r )
  2. {
  3. return l->libelle < r->libelle;
  4. }
  5. // ...
  6. niveau1->fils.sort( pred );


 
Au passage, tu noteras que ton tri ne va pas en profondeur, tu ne trie que les fils d'un noeud, pas les petits fils.
 
Edit : const


Message édité par theshockwave le 22-10-2009 à 16:59:05

---------------
last.fm
Reply

Marsh Posté le 22-10-2009 à 11:36:21    

merci de m'éclairer, j avoue que je suis dépassé mais je pense que tu l'as remarqué ;)
 
j'avais déjà essayer la même chose, le problème c'est que je ne peux pas l'utiliser dans ma classe noeud (en tout cas je n'ai pas réussi)
 
merci pour ta patience


---------------
----------------------------------------
Reply

Marsh Posté le 22-10-2009 à 12:01:43    

le prédicat ne doit pas être une fonction membre de ta classe ou alors il est nécessaire qu'il soit déclaré comme membre statique.
Montre ce que tu essayes et les erreurs que tu obtiens, ce sera plus rapide pour t'aider.


---------------
last.fm
Reply

Marsh Posté le 22-10-2009 à 14:29:52    

des const s'il vous plait !

Reply

Marsh Posté le 22-10-2009 à 16:59:37    

Taz a écrit :

des const s'il vous plait !


 
Here you are, my lord.
 

TheSamFrom1984 a écrit :


+1 ça fait mal aux yeux  [:delarue5]


 
merci pour la contribution


---------------
last.fm
Reply

Marsh Posté le 22-10-2009 à 23:47:03    

lol


---------------
.
Reply

Marsh Posté le 23-10-2009 à 19:53:13    

Bonjours tout le monde malgré vos remarques dure (méchante ?) mais surement mérité je reviens ;)
 
Alors j'ai pas mal avancé depuis la dernière fois mais j'ai changé mon fusil d'épaule pour le tri, maintenant j'eesaie d'insérer les élément directement à la bonne place plutôt que de trier, mais ca mache pas beaucoup mieux :(
 

Code :
  1. bool operator< (const Noeud *c1)
  2. {
  3.  return libelle > c1->libelle;
  4. }
  5. Noeud* ajouterFils(string texte)
  6. {
  7.  Noeud* nouveauNoeud = new Noeud(texte);
  8.  list<Noeud*>::iterator it;
  9.  it = fils.begin();
  10.  while (*it<nouveauNoeud)
  11.  {
  12.   ++it;       
  13.  }
  14.  fils.insert (it,nouveauNoeud);
  15.  return nouveauNoeud;
  16. }
  17. void afficher(int NbTab)
  18. {
  19.  if (!fils.empty())
  20.  {
  21.   insererTab(NbTab);
  22.   cout<<libelle<<endl;
  23.   list<Noeud*>::iterator it;
  24.   for (it=fils.begin(); it!=fils.end(); ++it)
  25.   {
  26.    (*it)->afficher(NbTab+1);
  27.   }
  28.  }
  29.  else
  30.  {
  31.   insererTab(NbTab);
  32.   cout<<libelle<<endl;
  33.  }
  34. }


Code :
  1. int main(void)
  2. {
  3. Noeud* niveau1=new Noeud("Niveau1" );
  4. niveau1->ajouterFils("Niveau20" );
  5. niveau1->ajouterFils("Niveau22" );
  6. niveau1->ajouterFils("Niveau23" );
  7. niveau1->ajouterFils("Niveau21" );
  8. niveau1->afficher(0);
  9. delete niveau1;
  10. return 0;
  11. }


 
résultat console :  

Code :
  1. Niveau1
  2.         Niveau20
  3.         Niveau22
  4.         Niveau23
  5.         Niveau21


 
Je n'arrive pas à trouver le fonctionnement des iterateurs.
 
merci ++


Message édité par espagnol49 le 23-10-2009 à 19:54:16

---------------
----------------------------------------
Reply

Marsh Posté le 24-10-2009 à 14:49:31    

forcément, tu compares encore et toujours des pointeurs ...
 
Nous ne sommes pas méchants, mais tu dois comprendre que :
 

Code :
  1. Noeud a, b;
  2. // ...
  3. if( a < b )
  4. // ...


 
ne fait pas du tout la même chose que :
 

Code :
  1. Noeud *a, *b;
  2. // ...
  3. if( a < b )
  4. // ...


 
Dans le premier cas, tu vas bien comparer tes instances de Noeud, dans le deuxième, tu vas comparer leur adresse mémoire !
 
Vérifie ce que tu manipules, quand tu as un itérateur ...
 
sinon, pour rechercher un itérateur dans un conteneur sur lequel tu peux itérer, tu devrais plutôt passer par un std::find_if et lui passer le prédicat qui va bien (je t'invite à jeter un oeil à bind2nd si tu t'y lances)


---------------
last.fm
Reply

Marsh Posté le 24-10-2009 à 17:14:33    

ok, cette fois je pense que j'ai compris, j'ai lu de la doc sur les iterateur et c'est un peu plus clair. une dernière question en ce qui concerne le destructeur de ma classe :
 

Code :
  1. ~Noeud()
  2. {
  3.  libelle="";
  4.  fils.clear();
  5. }


 
Est ce vraiment utile de le préciser ou c'est deja ce que fait le destructeur par defaut ? si c'est utile est ce efficace ? je ne me rend pas compte si toute les génération vont être supprimer.


---------------
----------------------------------------
Reply

Marsh Posté le 24-10-2009 à 17:48:48    

tu as fait à peu de choses près ce qu'un destructeur généré aurait fait, et, dans ton cas, ca ne revient pas du tout à ce que tu devrais faire. Sache qu'à tout appel à new doit correspondre un appel à delete, sans quoi, tu vas avoir une fuite mémoire. A toi de déterminer qui a la responsabilité de libérer des instances de Noeud (bien souvent, pour des raisons de symétrie, on a tendance à préférer que ce soit celui qui a alloué qui libère aussi la donnée)


Message édité par theshockwave le 24-10-2009 à 17:49:26

---------------
last.fm
Reply

Marsh Posté le 24-10-2009 à 18:29:10    

Je tendrais vers quelquechose comme ca :
 

Code :
  1. ~Noeud()
  2. {
  3.  libelle="";
  4.  fils.erase(fils.begin(),fils.end());
  5. }


 
si j'ai bien comprise fils.erase doit appeler le destructeur de noeud à chaque fois, le problème c'est que je ne vois pas comment faire intervenir un delete dans la boucle pour equilibre les new/delete.


---------------
----------------------------------------
Reply

Marsh Posté le 24-10-2009 à 19:01:29    

vuq ue tu manipules des pointeurs, ta liste ne va jamais se charger de les libérer pour toi, donc soit tu fais une boucle pour itérer sur la liste et détruire les objets pointés dans ton destructeur (auquel cas, il faut que tu croises les doigts pour que personne n'aie gardé de référence) soit être parti au départ sur une liste de pointeurs plutôt que directement une liste de Noeud, ce n'était peut-être pas une bonne idée. A toi de voir.


---------------
last.fm
Reply

Marsh Posté le 24-10-2009 à 19:54:40    

theshockwave a écrit :

vuq ue tu manipules des pointeurs, ta liste ne va jamais se charger de les libérer pour toi, donc soit tu fais une boucle pour itérer sur la liste et détruire les objets pointés dans ton destructeur (auquel cas, il faut que tu croises les doigts pour que personne n'aie gardé de référence) soit être parti au départ sur une liste de pointeurs plutôt que directement une liste de Noeud, ce n'était peut-être pas une bonne idée. A toi de voir.


 
Faut voir à faire els choses proprement. Le mieux ets d'avoir une std::list de shared_ptr ou equivalent.
Ca limitera les pb d'ownership

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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