IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Utilisation de la fonction HeapSort (algorithme de tri)


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 87
    Points : 43
    Points
    43
    Par défaut Utilisation de la fonction HeapSort (algorithme de tri)
    Bonjour à tous,
    Alors là je suis en train de me prendre la tête pour trier des arrêtes d'un maillage.
    En fait, le but du jeu c'est que, sur un maillage triangulaire, je récupère toutes les arrêtes du maillage. Mon idée est de récupérer les trois arrêtes de chaque triangle et ensuite d'enlever les doublons (le maillage est évidemment conforme).
    Chacune des arrêtes est définie par deux points A et B par exemple numérotés par le couple (a, b)

    Pour enlever les doublons mon idée était de trier les a par exemple (avec la fonction HeapSort) et après il est facile par comparaison des lignes successives du tableau d'enlever les doublons.

    Problème je peux trier les a mais comment garder le b qui forme un couple avec a?

    Si quelqu'un a une idée...
    Merci.

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Rend a et b dépendants l'un de l'autre...

    Soit en créant une structure particulière qui représente une arrête (mais dont la comparaison pour le tri ne s'intéresse qu'à a), soit, pourquoi pas, en utilisant tout simplement une std::pair, dont le premier élément serait a et le second serait b

    [EDIT]l'avantage d'une "spécialisation" de la std::pair, c'est que, si tu te sert de cette spécialisation comme clé d'un conteneur associatif (set ou map), il ne pourra plus y avoir que une seule fois [point1, point2] dans l'ensemble (mais [point2,point1] reste possible :p)

    Dés lors, le simple fait d'ajouter les différentes arrêtes dans le conteneur supprimera les doublons

    Mais sous-entend que tu as un predicat "less" pour ton point
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 87
    Points : 43
    Points
    43
    Par défaut
    Tout d abord merci pour tes réponses. Ensuite, pourquoi il n y aurait plus de doublons en utilisant ta méthode?? Et qu est ce qu un prédicat "less"?

    Merci...

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Parce que le propre des conteneurs associatifs est que leur clé est unique...

    Pour te permettre de savoir ce qu'est un prédicat, je préfère te réorienter vers l'entrée de la FAQ correspondante, ainsi que vers l'entrée précédente.

    Si je te parle de "less", c'est parce que les différents algorithmes de tri de la STL utilisent ce prédicat particulier, qui signifie "plus petit", pour travailler.

    Il faut noter que c'est le seul prédicat réellement utilisé, ainsi, la STL considère que:
    • Si a n'est pas plus petit que b et que
    • b n'est pas plus petit que a alors
    • a est égal à b

    Dés lors, si tu permet à ton point de répondre à la question "es tu plus petit que l'autre point ", ton point pourra servir comme clé dans un conteneur associatif

    Il faut cependant prendre en compte le fait que, si tu a deux points a et b, l'arrete [a,b] et l'arrete [b,a] seront être considérées comme étant différentes si elles servent de clé dans une std::pair.

    Selon que tu considère que deux arrêtes sont identiques si elle ont seulement la même orientation ou qu'elles sont identiques si elles ont la même orientation et la même direction, il n'est pas impossible que tu doive mettre en place une vérification de l'existence d'une permutation entre a et b
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 87
    Points : 43
    Points
    43
    Par défaut
    Merci encore.

    Mais le fait que deux arretes identiques sont "différentes" selon leurs orientations me dérange un peu... Alors j ai écrit une nouvelle version de HeapSort:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    template<class T>
    void  HeapSort(T *c,long n) // on a un tableau sur lequel on travaille par adresse memoire
    {
      long l,j,r,i;
      T crit;
      c--; // on decale de 1 pour que le tableau commence a 1
      if( n <= 1) return;
      l = n/2 + 1;
      r = n;
      while (1) { // label 2
        if(l <= 1 ) { // label 20
          crit[0] = c[r][0];
          c[r--][0] = c[1][0];
          crit[1] = c[r][1];
          c[r--][1] = c[1][1];
        if ( r == 1 ) { c[1][0]=crit[0]; c[1][1]=crit[1];  return;}
        } 
        else  {crit[0] = c[--l][0]; crit[1] = c[--l][1]; }
        j=l;
        while (1) {// label 4
          i=j;
          j=2*j;
          if  (j>r) {c[i][0]=crit[0]; c[i][1]=crit[1];
            break;} 
          if ((j<r) && (c[j][0] < c[j+1][0])) j++; // L5
          if (crit[0] < c[j][0]) { c[i][0]=c[j][0]; c[i][1]=c[j][1];
          }
          else {c[i][0]=crit[0];c[i][1]=crit[1];
           break;} 
        }
    Mais ça ne marche pas, mon tableau est modifié mais ça n a ni queue ni tête!

    Peut être que l ereur vient aussi de l appel à HeapSort qui est bancal aussi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    HeapSort(tre,Th.nt*3 );
    tre: triangle edge
    Th.nt : nombre de triangles du maillage


    Voilà, thanks.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par Butterfly83 Voir le message
    Merci encore.

    Mais le fait que deux arretes identiques sont "différentes" selon leurs orientations me dérange un peu... Alors j ai écrit une nouvelle version de HeapSort:
    Réécrire la fonction de comparaison ne suffirait-il pas?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    En plus, si tu part sur le principe d'une classe qui va se charger de gérer les différentes arrêtes sur base de ce que je te propose, cela peut très bien tourner sur quelque chose de relativement simple... meme si on en vient à oublier le heapsort :p

    Je m'explique:

    Tu part sur une classe (ou une structure) Point "classique", avec un foncteur permettant de déterminer si un point est plus petit qu'un autre (le fameux predicat "less" )

    Tu crée, pour la facilité, un alias
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef std::pair<Point,Point> Arrete;
    qui te permet de représenter une arrête avec son point "de départ" et son point "d'arrivée".

    la création d'une arrête sous cette forme se fait sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Arrete obj=std::make_pair(point1, point2);
    Tu crées ensuite une classe "GestionnaireArrete" (par exemple) qui se structure sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class GestionnaireArrete
    {
        public:
            /* les alias qui permettent d'utiliser notre gestionnaire comme les
             * coneteneurs classiques ;)
             */
            typedef std::set<Arrete>::iterator iterator;
            typedef std::set<Arrete>::const_iterator const_iterator;
            GestionnaireArrete(){}//rien à faire
            ~GestionnaireArrete(){}//sympa, tout se fait automatiquement ;)
            void insertArrete(const Arrete&); // pourrait renvoyer l'arrete ;)
            iterator& begin(); //pour obtenir la première arrete
            iterator& end(); //quand on arrive à end, on a vu toutes les arretes ;)
            iterator& operator++();//permet de passer à l'élément suivant
        private:
            std::set<Arrete> allar;//va contenir toutes les arretes ;)
            iterator ite;
    };
    La méthode intéressante est insertArrete car pour begin(), il suffit d'initialiser ite à allar.begin() et de renvoyer it, pour end(), il suffit de renvoyer allar.end(), et, pour operator++, il suffit d'incrémenter ite et de le renvoyer (rien de particulier, en somme )

    Toi, tu voudrais qu'avec deux points (p1 et p2, pour l'exemple), les arrêtes créées sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Arrete ar1=std::make_pair(p1,p2);
    Arrete ar2=std::make_pair(p2,p1);
    soient considérées comme étant identiques

    La solution est relativement simple: dans la méthode insertArrete, il *suffit* de vérifier la présence de la permutation (autrement dit d'une arrête [p2,p1] pour ar1 ou d'une arrete [p1,p2] pour ar2

    Cela peut se faire très facilement en implémentant la méthode sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void GestionnaireArrete:: insertArrete(const Arrete& toadd)
    {
        if(allar.find(std::make_pair(toadd.second,toadd.first))==allar.end())
            allar.insert(toadd);
    }
    ou, si tu préfères un code un peu plus verbeux sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void GestionnaireArrete:: insertArrete(const Arrete& toadd)
    {
        /* création de l'arrête "permutée" */
        Arrete temp=std::make_pair(toadd.second, toadd.first);
        /* on insere l'orginal si on ne trouve pas la permutation */
        if(allar.find(temp)==allar.end())
            allar.insert(toadd);
    }
    En quelques lignes à peine, tu obtiens quelque chose qui sera sans doute bien plus efficace que ton HeapSort
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre éclairé Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Dépêche-toi de corriger cette faute d'orthographe affreuse : arrête -> arête !

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par HanLee Voir le message
    Dépêche-toi de corriger cette faute d'orthographe affreuse : arrête -> arête !
    Hé bien non, tiens... j'ai décidé d'arrêter mes arêtes
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 87
    Points : 43
    Points
    43
    Par défaut
    Merci pour vos réponses.

    Sinon, en quoi la complexité de ton algorithme serait moins grande? HeapSort étant en O(nlog(n)) opérations?

    Merci.

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Je n'ai pas dit que la complexité serait moins grande, étant donné que la recherche se fait également en O=log(n).

    Ce que je sous-entend, c'est que, du point de vue de l'écriture, tu t'évites une série de problèmes grâce à la gestion dynamique automatique de la mémoire des conteneurs de la STL, que tu obtiens un code plus compact, plus sécurisé, et, au final, plus facilement compréhensible que si tu dois écrire ta fonction HeapSort à la main...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Excel : utilisation de la fonction tri
    Par Hicks90 dans le forum Débuter
    Réponses: 9
    Dernier message: 12/12/2012, 02h04
  2. Tri après l'utilisation de la fonction "explode"
    Par celinedecham dans le forum Langage
    Réponses: 7
    Dernier message: 04/10/2008, 20h40
  3. Utilisation de la fonction de déploiement
    Par mchicoix dans le forum XMLRAD
    Réponses: 4
    Dernier message: 01/03/2005, 14h35
  4. Utilisation de la fonction qsort
    Par Jsmeline dans le forum C
    Réponses: 8
    Dernier message: 28/01/2005, 12h40
  5. [LG]librairies : utiliser seulement quelques fonctions
    Par wwwroom dans le forum Langage
    Réponses: 13
    Dernier message: 14/05/2004, 22h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo