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

SL & STL C++ Discussion :

foncteur pour trier/classer


Sujet :

SL & STL C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 11
    Par défaut foncteur pour trier/classer
    Bonjour,
    j'ai fait une classe pour trier des std::vector<double>, que j'aimerais pouvoir utiliser comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #include "sorter.h"
     
    std::vector<double> values;
    std::vector<int> indices, ranks;
    initialize(values); // remplit values avec des double
     
    Sorter mySorter() // instancie le trieur
    mySorter.sort(values, indices); // indices récupère les indices des values décroissants
    mySorter.rank(values, ranks); // Autre retour possible : ranks[i] vaut le rang de value[i]
    Voici les fichiers de ma classe :

    sorter.cpp :
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #include "sorter.h"
     
      Sorter::Sorter()
      {
      }
     
      Sorter::Sorter(vector<double>& values, vector<int>& indices)
      {
    	  m_values = &values;
    	  sort (values, indices);
      }
     
      void Sorter::rank(vector<double>& values, vector<int>& ranks)
      {
        int n = values.size();
        if (ranks.size() != n)
          ranks.resize(n);
    	vector<int> indices;
    	sort(values, indices);
     
    	double lastVal = values[indices[0]];
    	int lastIndex = 0;
    	for (int i = 2; i < n; i++) {
    		if (values[indices[i]] = lastVal)
    			ranks[indices[i]] = 	lastIndex;
    		else {
    			ranks[indices[i]] = i;
    			lastIndex = i;
    		}
    		lastVal = values[indices[i]];
    	}
     
      }
     
      void Sorter::sort(vector<double>& values, vector<int>& indices)
      {
        int n = values.size();
        if (indices.size() != n)
          indices.resize(n);
        for (int i = 0; i< n; i++)
          indices[i] = i;
     
        m_values = &values;
    	std::sort(indices.begin(), indices.end(), *this);
     
      }
     
      bool Sorter::operator()(int i, int j)
      {
      	  if((*m_values)[i] > (*m_values)[j])
    		return true;
    	  return false;
      }
     
      Sorter::~Sorter()
      {
      }
    sorter.h :
    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
    #ifndef _sorter_h
    #define _sorter_h
     
    #include <functional>
    #include <algorithm>
    #include <vector>
    #include <iostream>
     
    using namespace std;
     
    class Sorter : public std::binary_function<int, int, bool>
    {
    	public:
     
    	Sorter();
    	Sorter(vector<double>&, vector<int>&);
    	void rank(vector<double>&, vector<int>&);
    	void sort(vector<double>&, vector<int>&);
     
    	bool operator()(int i, int j);
     
     
    	~Sorter();
     
     
    	private:
    	vector<double>* m_values;
    };
     
    #endif
    On en vient à ma question :

    Le tri fonctionne bien quand je l'execute dans un constructeur, mais pourquoi le code suivant ne compile-t-il pas (sous visual studio express 2008) ?:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Sorter mySorter(values, indices); // OK
    mySorter.sort(values, indices); // ne compile pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error C2228: la partie gauche de '.sort' doit avoir un class/struct/union

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    as tu écrit cela?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Sorter mySorter(); 
    mySorter.sort(values, indices);
    si oui c'est normale,
    représente l'entête d'une fonction pour le compilateur.
    Il faut que tu le déclare comme cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Sorter mySorter;
    mySorter.sort(values, indices);

    si non, je ne voie pas.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 11
    Par défaut
    snif, j'ai honte.
    Merci en tout cas :-)

    Sinon, j'ai une autre question :

    J'aimerais pouvoir utiliser différentes méthodes de tri, basées sur des opérateurs divers et variés. Par exemple :

    dans sorter.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	bool asc(int i, int j);
    dans sorter.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
      bool Sorter::asc(int i, int j)
      {
      	  if((*m_values)[i] > (*m_values)[j])
    		return true;
    	  return false;
      }
    et remplacer dans Sorter::sort la ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    	std::sort(indices.begin(), indices.end(), *this);
    par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    	std::sort(indices.begin(), indices.end(), asc);
    Comme ils le font avec la fonction "myfunction" dans http://www.cplusplus.com/reference/algorithm/sort.html

    Mais le compilateur demande des arguments pour ma fonction asc. Des idées?

    Mertci beaucoup!

  4. #4
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 294
    Billets dans le blog
    2
    Par défaut
    Ben ça dépend de ce que contient la variable indice.

    Si tu veux, je te propose un exemple que je pense être assez didactique pour comprendre ce genre de choses:

    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    #include <string>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    #include <iterator>
     
    #include <time.h>
     
    using namespace std;
     
    struct Dum{
    	Dum( int n ) : num(n) {}
    	int num;
    };
     
    std::ostream & operator << ( std::ostream & ost, const Dum & dum ) {
    	ost << dum.num;
    	return ost;
    }
     
    struct MyCompare{
    	bool operator () ( const Dum & left, const Dum & right ) {
    		return ( left.num < right.num );
    	}
    };
     
    int main( int argc, char** argv )
    {
    	std::vector<Dum> v;
    	srand( time( 0 ) );
    	for( int i=0; i<20; i++ ) v.push_back( Dum( ( rand() * i ) % 50 ) );
     
    	std::copy( v.begin(), v.end(), std::ostream_iterator<Dum>( std::cout, " " ) );
    	std::cout << std::endl;
    	std::sort( v.begin(), v.end(), MyCompare() );
    	std::cout << "sort:" << std::endl;
    	std::copy( v.begin(), v.end(), std::ostream_iterator<Dum>( std::cout, " " ) );
     
    	// attend une touche clavier pour fermer le programme
    	std::cout << std::endl << "end" << std::endl;
    	std::cin.get();
    	return 0;
    }
    Hope it helps.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 11
    Par défaut
    Salut,
    Merci pour vos réponses. En fait dans vos exemples vous proposez la 2ème solution du lien que j'avais posté (celui où l'opérateur est défini dans une structure "myclass").

    http://www.cplusplus.com/reference/algorithm/sort.html

    Ce que j'aimerais faire, c'est y arriver avec la 1ère solution : c'est à dire en définissant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool myfunction (int i,int j) { return (i<j); }
    Ca m'éviterait de créer une structure par opérateur.

  6. #6
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par tistouforever Voir le message
    Ce que j'aimerais faire, c'est y arriver avec la 1ère solution : c'est à dire en définissant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bool myfunction (int i,int j) { return (i<j); }
    Tu ne pourra pas tant que tu as besoin d'élément externe à ton foncteur, comme le vector qui contient les elements servant à trier les indices.


    Pourquoi un pointeur sur un vector????????????????

  7. #7
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Il faudrait que asc soit un prédicat
    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
     
    struct asc
    {
         asc(const vector<double> &val)
         :m_values(val)
         {}
     
         bool operator()(int i,int j)
         {
              return m_values[i] > m_values[j];
         }
     
     
     
        const vector<double> &m_values
    };
     
    ...
    std::sort(indices.begin(), indices.end(), asc(m_values);

    J'ai du mal à comprendre pourquoi faire un foncteur qui s'utilise lui même pour faire quelque chose....
    Le foncteur n'est la que pour faire un traitement.

    Que cherche tu à faire??

    Par contre pourquoi un pointeur sur un vector????????????????

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    11
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 11
    Par défaut
    Citation Envoyé par Mongaulois Voir le message
    J'ai du mal à comprendre pourquoi faire un foncteur qui s'utilise lui même pour faire quelque chose.
    Mon foncteur a besoin de contenir le vecteur de valeurs pour pouvoir faire son tri des indices.

  9. #9
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par tistouforever Voir le message
    Mon foncteur a besoin de contenir le vecteur de valeurs pour pouvoir faire son tri des indices.
    Ca ok, mais je ne mettrais pas cela dans un foncteur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::sort(indices.begin(), indices.end(), *this);

    j'aurais fit un truc comme cela
    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
     
    struct sorter
    {
         asc(const vector<double> &val)
         :m_values(val)
         {}
     
         bool operator()(int i,int j)
         {
              return m_values[i] < m_values[j];
         }
         const vector<double> &m_values
    };
     
     
    std::vector<double> tab;
    std::vector<int>       indice;
    ...
     
     
    std::sort(indice.begin(),indice.end(),sorter(tab));

Discussions similaires

  1. probleme de script pour trier dynamiquement un tableau
    Par K_!!! dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 16/02/2006, 16h46
  2. [XSL] Comment faire pour trier de cette façon ?
    Par shupa dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 30/06/2005, 17h39
  3. Algorithme pour trier trois nombres
    Par legosam dans le forum Algorithmes et structures de données
    Réponses: 9
    Dernier message: 17/01/2005, 21h47
  4. [ STRUTS ][ JSP ][ ArrayList] un lien pour trier
    Par LoulouFifi dans le forum Servlets/JSP
    Réponses: 7
    Dernier message: 03/02/2004, 17h24
  5. Créer une vue pour trier une requete UNION ?
    Par Etienne Bar dans le forum SQL
    Réponses: 3
    Dernier message: 03/01/2003, 20h22

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