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

MFC Discussion :

Tri rapide d'une CListCtrl


Sujet :

MFC

  1. #1
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut Tri rapide d'une CListCtrl
    Bonjour

    Depuis un moment je recherche une CListCtrl capable de réaliser un tri rapide sur des milliers de lignes. Car celle fournis n'est pas rapide du tout mais pas du tout.

    J'ai donc cherché et cherché mais je n'ai pratiquement rien trouvé. A part des algorithmes purs qu'il faudrait spécialement adapté pour une CListCtrl.

    Par contre j'ai trouvé cet article sur CodeGuru "Quick Sort Algorithm Comparing Any Data Type"
    Ca fonctionne correctement quand la liste est dans le désordre mais quand je reclique sur l'entête de la colonne pour faire le tri inverse, au bout de 10-15 minutes j'ai eu un gros STACK OVERFLOW.
    Donc cette solution n'est pas viable.

    Mais je suis certain qu'il existe des personnes qui ont dû implémenter ce genre de chose. Alors s'il vous plait partagé ce bout de code avec nous.

    Merci d'avance

  2. #2
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    En continuant à chercher j'ai trouvé un site qui permet de faire des comparaisons d'algo de tri.

    http://vision.bc.edu/~dmartin/teachi...-html/all.html

    Mais concrétement ça ne m'aide pas pour ma solution mais ça permet d'avoir une idée des tris.

    Mais j'ai eu une idée con. Si une colonne est déjà trié dans un sens. Par exemple avec un tri rapide.
    Donc quand l'utilisateur veut inverser le sens il suffit de prendre le premier de la liste et le mettre à la fin.
    Le problème c'est si l'utilisateur modifie ou ajout un élément.

    A voir donc

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    303
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2005
    Messages : 303
    Par défaut
    Salut,
    Pour ma part je n'ai rien trouvé de mieux que les tris disponibles dans la stl (algo ou container). Ils sont rapides et fiables.
    André

  4. #4
    Membre confirmé
    Inscrit en
    Novembre 2007
    Messages
    66
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 66
    Par défaut
    salut,
    essaie avec le fichier joint.
    Fichiers attachés Fichiers attachés

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Mon conseil: Virtual list + algos stl.

  6. #6
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    J'ai bien eu l'idée de faire du OwnerData (VirtualList) mais dans mon projet les données de la liste viennent de différentes sources.
    A moins que je crée des données temporaires dans ma liste contenant toutes ces données. J'utilise le OnGetDispInfo avec ces données stockés puis que j'utilise les stl pour faire le tri.

    Arréter moi si je m'égare.

    Par contre pour les stl je ne sais pas comment faire. Avec quel algo, container, ...

  7. #7
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    Je suis un peu fénéant et je cherche un container stl de type tableau à deux dimensions pouvant être trier.
    J'ai l'impression que je recherche l'impossible mais je cherche.

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par vanitom Voir le message
    J'ai bien eu l'idée de faire du OwnerData (VirtualList) mais dans mon projet les données de la liste viennent de différentes sources.
    Et alors?
    Citation Envoyé par vanitom Voir le message
    A moins que je crée des données temporaires dans ma liste contenant toutes ces données.
    Que sont tes sources? Tu peux les interroger dynamiquement sans perdre en perf?
    Citation Envoyé par vanitom Voir le message
    J'utilise le OnGetDispInfo avec ces données stockés puis que j'utilise les stl pour faire le tri.


    Citation Envoyé par vanitom Voir le message
    Arréter moi si je m'égare.
    La route est droite mais la pente est forte: courage!

    Citation Envoyé par vanitom Voir le message
    Par contre pour les stl je ne sais pas comment faire. Avec quel algo, container, ...
    Pour le choix du container, je dirais, à priori un std::vector<std::vector<string> >: un vecteur de lignes, les lignes étant un vecteur de colonnes, les colonnes étant les chaînes!
    Ensuite, comparaison sur la chaîne correspondant à la colonne de tri.
    Pour un choix de container adapté à ta solution, tu peux utiliser le tableau ici ou celui-ci.

  9. #9
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    Ok merci pour toutes les informations.

    Je pense que je vais choisir des list plutot que des vector.

    Par contre je vais mettre ça en pose quelques jours pour faire d'autres choses soit disant plus important.
    Mais je reviendrais dans ce post s'il m'arrive encore des problèmes.

    En tout cas merci pour tout.

  10. #10
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    salut,
    l'avantage de la liste sur le vector c'est qu'il n'y pas de ré allocation mémoire de l'ensemble des éléments +1 pour chaque insertion...

  11. #11
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    Ca y est depuis hier je m'y suis mis.

    J'ai remplis toute ma structure de données.
    Voici la structure que j'utilise :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    list < vector < string > >
    J'ai mis en place le ON_NOTIFY_REFLECT pour récupérer le OnGetDispInfo.

    Maintenant j'ai une question :

    Dans le OnGetDispInfo, on me donne un nItem. Comment je fais pour savoir de quel élément de ma liste, ça correspond.

    Là je suis perdu.
    J'ai l'impression que le plus simple serait d'utiliser un vector à la place d'une list mais j'ai cru comprendre que c'était mieux au niveau mémoire.

  12. #12
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    J'avais idée de mettre dans l'item data de la vrai liste, un pointeur vers l'objet contenu dans la liste.

    Mais le problème se serait lors du tri. L'ordre aura changer et je pointerais toujours vers le même élément même s'il n'est plus à la même place dans list.

  13. #13
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    En attendant je vais scanner la liste pour aller chercher l'élément n de la liste.
    D'ailleurs c'est peut être la bonne méthode, j'en sais rien encore.

  14. #14
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    De mémoire, c'est à toi d'associer l'index de LVN_GETDISPINFO avec celui de ta liste: quelque chose comme vector<>::[NMLVDISPINFO .item.iItem].
    Pour une list<>. J'ai peur qu'il ne te faille faire un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    list<>::iterator Iterateur;
    Iterateur = ma_liste.begin();
    while(iItem>0){
       ++Iterateur;
       --iItem;
    }
    Du coup, le vecteur est peut être plus adéquat!
    Pour le problème d'allocation du vecteur, il te suffit d'utiliser vector<>::reserve pour allouer tout un bloc dès le début. Cela peut être intéressant si ton vecteur ne va pas beaucoup bouger en taille pendant sa durée de vie.

  15. #15
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    Ça y est je viens de finir le tri est c'est vraiment top.

    Trier 100 000 lignes en moins 12 secondes. Je ne m'attendais pas à ça c'est top.

    Par contre il reste toujours un problème lié aux messages précédent.
    Quand le OnGetDispInfo me demande le texte de l'item 1 ou 10 ça rapide. Mais il me demande le texte de l'item 45 000 c'est l'apocalypse.
    Ce qui serait top, c'est une sorte de map en l'item et l'iterator de la liste. Mais j'ai peur que l'iterator se déplace en même temps quand je tri ma liste. Et donc que le tri ne serve plus à rien.
    Voici mon code du OnGetDispInfo pour avoir votre avis. Et savoir s'il y aurait des optimisations possible.
    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
     
     
    BOOL TknoListCtrlEx::OnGetDispInfo ( NMHDR * pNotifyStruct, LRESULT* result )
    {
    	NMLVDISPINFO *pdi = (NMLVDISPINFO*) pNotifyStruct;
     
     
    	list<TknoListCtrlRow>::iterator itCurrent = m_lstRows.begin ( );
     
    	for ( int i = 0; i < pdi->item.iItem; i++, itCurrent++ );
     
    	TknoListCtrlRow * pRow = &(*itCurrent);
    	ASSERT ( pRow );
    	if ( pRow != NULL )
    	{	
    		if ( pdi->item.mask & LVIF_TEXT ) //valid text buffer?
    		{
    			CString sText; pRow->GetText ( pdi->item.iSubItem, sText );
                lstrcpy ( pdi->item.pszText, sText);
    		}
    	}
     
    	*result = 0l;
     
    	return TRUE;
    }
    Pour 3DArchi, j'ai décidé d'utiliser une stl::list pour éviter trop de problème au niveau de la mémoire.

  16. #16
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Pour répondre dans l'ordre:
    1/une map entre indice et iterateur: très mauvaise idée. Les itérateurs ne sont pas sensés être maintenu (car l'ajout, la suppression ou le réordonnancement de tes éléments peut invalider ton itérateur),
    2/ Entre list et vector: j'ai fait quelques tests en release avec Visual: perf identique ou voisine jusqu'à 100 000 éléments. Après, j'ai pas testé. Conclusion: prend plutôt un vector qui sera beaucoup plus performant pour accéder au nième élément!
    3/ Préfère ++itCurrent à itCurrent++,
    4/ Pourquoi prendre un pointeur: TknoListCtrlRow * pRow = &(*itCurrent); ? En plus ASSERT(pRow!=NULL) ne va jamais claquer.
    5/ Pour blender, tu devrais aussi vérifier que itCurrent ne dépasse jamais list<>::end().
    6/ Si vraiment tu veux rester avec la liste (mais je pense que c'est une mauvaise idée), regarde dans MSDN sur les points spécifiques au cache.

  17. #17
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    Merci pour tous ces conseils. C'est toujours utile d'avoir un avis sur ce genre de chose.

    Mais j'ai quelques questions par rapport à tes commentaires :
    Entre list et vector: j'ai fait quelques tests en release avec Visual: perf identique ou voisine jusqu'à 100 000 éléments. Après, j'ai pas testé. Conclusion: prend plutôt un vector qui sera beaucoup plus performant pour accéder au nième élément!
    Je pense que je vais passer au vector pour tester. Il faudra juste que je demande avant le remplissage la taille du vector en y ajoutant 10% pour éviter la réallocation pour une bourde.



    Préfère ++itCurrent à itCurrent++,
    Pourquoi c'est mieux ?
    Si je fais au début de ma boucle, je loupe la première valeur. Par contre à la fin c'est bon.



    Pourquoi prendre un pointeur: TknoListCtrlRow * pRow = &(*itCurrent); ? En plus ASSERT(pRow!=NULL) ne va jamais claquer.
    Effectivement c'est mes habitudes de tester mes pointeurs. Mais c'est vrai que c'est con. Comme tu as du le remarquer j'ai vraiment pas l'habitude avec les STL. D'où toutes les questions.



    Si vraiment tu veux rester avec la liste (mais je pense que c'est une mauvaise idée), regarde dans MSDN sur les points spécifiques au cache.
    Je pense que je vais effectivement utiliser un systeme de cache mais je ne connaissais le système proposer. J'avoue que j'ai pas tout compris mais je vais m'y attarder un peu pour faire ça proprement. Mais ça n'a pas l'air très facile. A voir donc.
    En attendant la solution ci-dessus, je vais voir pour le gérer moi même. Je vais garder en cache la "ligne" en cours d'affichage. Ca m'évitera de recherche n fois le même élément dans la list ou le vector.




    Encore merci pour votre aide. Je vous tiens au courant de l'évolution.

  18. #18
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    salut,
    le vector ré alloue un bloc mémoire de l'ensemble +1 pour insérer le nouvel élément.
    la list non ,
    un test de performance entre list et vector dépend de ce que l'on stock ...
    plus le bloc mémoire est important plus les différences devraient être criantes.., si on stock des pointeurs le coût cpu sera moindre ..
    la réservation d'une place à la construction du vector peut être une réponse si on connaît la taille à l'avance, ou utiliser reserve() qui n'initialise pas les valeurs.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    vector<string> vec;
    vec.reserve(1000);
    la pre incrementation (++p) ne crée pas de valeur temporaire à retourner,
    la post incrémentation (p++) doit créer une variable temporaire parce qu'elle retourne la valeur p avant l'incrémentation.
    il vaut donc mieux faire ++p que p++ sur un itérateur...

  19. #19
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Exemple de test:
    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
     
    #include <iostream>
    #include <list>
    #include <vector>
    #include <iterator>
    #include <functional>
    #include <boost/bind.hpp>
    #include <boost/iterator/counting_iterator.hpp>
    #include <time.h>
     
    template<template<class,class > class Conteneur, class T, class A, class Fonction >
    void Tester(const std::string &NomConteneur, const std::string &NomFonction, Conteneur<T,A> & Objet, Fonction P_f)
    {
       clock_t L_t0;
       clock_t L_tTotal;
       size_t L_NbrElements = Objet.size();
       std::cout<<"Temps "<<NomFonction<<" "<<NomConteneur<<" : ";
       L_t0 = clock();
       P_f(Objet);
       L_tTotal = clock()-L_t0;
       std::cout<<L_tTotal<< " ( "<<L_NbrElements<<" ), "<<(double)L_tTotal/(double)L_NbrElements<<" (1)\n";
    }
     
    template<class T>
    void Detruire(T &Element)
    {
       delete &Element;
    }
     
    template<class T>
    void RemoveAll(T &Element)
    {
          while(!Element.empty()){
             Element.pop_back();
          }
    }
     
    template<class T>
    void EraseFirst(T &Element)
    {
          while(!Element.empty()){
             Element.erase(Element.begin());
          }
    }
     
    template<class T>
    void EraseLast(T &Element)
    {
          while(!Element.empty()){
             typename T::iterator L_fin;
             L_fin = Element.end();
             --L_fin;
             Element.erase(L_fin);
          }
    }
     
    template<class T>
    void Inserer1Debut(T&Element)
    {
       Element.insert(Element.begin(),1);
    }
     
    template<class T>
    void Inserer1Fin(T&Element)
    {
       Element.insert(Element.begin(),1);
    }
     
    template<class T>
    void InsererNMilieu(T&Element, int NbrElements, typename T::iterator Milieu)
    {
       Element.template insert<boost::counting_iterator<int> >(
          Milieu
          ,boost::counting_iterator<int>(0)
          ,boost::counting_iterator<int>(NbrElements)
       );
    }
     
     
    template<template<class, class > class Conteneur>
    void BatterieTest(const std::string &NomConteneur, const int &P_iNbrElement)
    {
       typedef Conteneur<int, std::allocator<int> > TypeConteneur;
       TypeConteneur *L_pConteneur;
       L_pConteneur = new TypeConteneur;
       std::cout<<"Taille "<<NomConteneur<<" : "<<P_iNbrElement<<"\n";
       Tester(NomConteneur,"resize",*L_pConteneur,boost::bind(&TypeConteneur::resize,_1,P_iNbrElement,0));
       Tester(NomConteneur,"removeAll/pop_back",*L_pConteneur,boost::bind(RemoveAll<TypeConteneur > ,_1));
       (*L_pConteneur).resize(P_iNbrElement);
       Tester(NomConteneur,"erase(begin)",*L_pConteneur,boost::bind(EraseFirst<TypeConteneur > ,_1));
       (*L_pConteneur).resize(P_iNbrElement);
       Tester(NomConteneur,"erase(end)",*L_pConteneur,boost::bind(EraseLast<TypeConteneur > ,_1));
       (*L_pConteneur).resize(P_iNbrElement);
       Tester(NomConteneur,"push_back",*L_pConteneur,boost::bind(&TypeConteneur::push_back ,_1,1));
       (*L_pConteneur).resize(P_iNbrElement);
       Tester(NomConteneur,"clear",*L_pConteneur,boost::bind(&TypeConteneur::clear,_1));
       (*L_pConteneur).resize(P_iNbrElement);
       Tester(NomConteneur,"insert(1,begin)",*L_pConteneur,boost::bind(Inserer1Debut<TypeConteneur > ,_1));
       Tester(NomConteneur,"insert(1,end)",*L_pConteneur,boost::bind(Inserer1Fin<TypeConteneur > ,_1));
       typename TypeConteneur::iterator L_iMilieu;
       L_iMilieu = L_pConteneur->begin();
       int L_iTaille = L_pConteneur->size()/2;
       while(L_iTaille>0){
          ++L_iMilieu;--L_iTaille;
       }
       Tester(NomConteneur,"insert(100000,milieu)",*L_pConteneur,boost::bind(InsererNMilieu<TypeConteneur > ,_1,100000,L_iMilieu));
     
       Tester(NomConteneur,"delete",*L_pConteneur,boost::bind(Detruire<TypeConteneur > ,_1));
       std::cout<<std::endl;
    }
     
    int main()
    {
       static const int L_ciNbrElements = 100000;
       BatterieTest<std::vector>("Vecteur",L_ciNbrElements);
       BatterieTest<std::list>("Liste",L_ciNbrElements);
     
       std::cout<<"Fin test"<<std::endl;
     
       return getchar();
     
     
    }
    Résultats avec gcc (release -o3):
    Taille Vecteur : 100000
    Temps resize Vecteur : 0 ( 0 ), -1.#IND (1)
    Temps removeAll/pop_back Vecteur : 0 ( 100000 ), 0 (1)
    Temps erase(begin) Vecteur : 3093 ( 100000 ), 0.03093 (1)
    Temps erase(end) Vecteur : 0 ( 100000 ), 0 (1)
    Temps push_back Vecteur : 0 ( 100000 ), 0 (1)
    Temps clear Vecteur : 0 ( 100000 ), 0 (1)
    Temps insert(1,begin) Vecteur : 0 ( 100000 ), 0 (1)
    Temps insert(1,end) Vecteur : 0 ( 100001 ), 0 (1)
    Temps insert(100000,milieu) Vecteur : 0 ( 100002 ), 0 (1)
    Temps delete Vecteur : 0 ( 200002 ), 0 (1)

    Taille Liste : 100000
    Temps resize Liste : 16 ( 0 ), 1.#INF (1)
    Temps removeAll/pop_back Liste : 15 ( 100000 ), 0.00015 (1)
    Temps erase(begin) Liste : 15 ( 100000 ), 0.00015 (1)
    Temps erase(end) Liste : 16 ( 100000 ), 0.00016 (1)
    Temps push_back Liste : 0 ( 100000 ), 0 (1)
    Temps clear Liste : 16 ( 100000 ), 0.00016 (1)
    Temps insert(1,begin) Liste : 0 ( 100000 ), 0 (1)
    Temps insert(1,end) Liste : 0 ( 100001 ), 0 (1)
    Temps insert(100000,milieu) Liste : 16 ( 100002 ), 0.000159997 (1)
    Temps delete Liste : 31 ( 200002 ), 0.000154998 (1)

    Fin test
    Avec visual C++ (release + /O2 /Ob2 /Oi /Ot + undef _HAS_ITERATOR_DEBUGGING;_SECURE_SCL):
    Taille Vecteur : 100000
    Temps resize Vecteur : 0 ( 0 ), -1.#IND (1)
    Temps removeAll/pop_back Vecteur : 0 ( 100000 ), 0 (1)
    Temps erase(begin) Vecteur : 3110 ( 100000 ), 0.0311 (1)
    Temps erase(end) Vecteur : 0 ( 100000 ), 0 (1)
    Temps push_front Vecteur : 0 ( 100000 ), 0 (1)
    Temps clear Vecteur : 0 ( 100000 ), 0 (1)
    Temps insert(1,begin) Vecteur : 0 ( 100000 ), 0 (1)
    Temps insert(1,end) Vecteur : 0 ( 100001 ), 0 (1)
    Temps insert(100000,milieu) Vecteur : 0 ( 100002 ), 0 (1)
    Temps delete Vecteur : 0 ( 200002 ), 0 (1)

    Taille Liste : 100000
    Temps resize Liste : 15 ( 0 ), 1.#INF (1)
    Temps removeAll/pop_back Liste : 16 ( 100000 ), 0.00016 (1)
    Temps erase(begin) Liste : 0 ( 100000 ), 0 (1)
    Temps erase(end) Liste : 31 ( 100000 ), 0.00031 (1)
    Temps push_front Liste : 0 ( 100000 ), 0 (1)
    Temps clear Liste : 16 ( 100000 ), 0.00016 (1)
    Temps insert(1,begin) Liste : 0 ( 100000 ), 0 (1)
    Temps insert(1,end) Liste : 0 ( 100001 ), 0 (1)
    Temps insert(100000,milieu) Liste : 16 ( 100002 ), 0.000159997 (1)
    Temps delete Liste : 31 ( 200002 ), 0.000154998 (1)

    Fin test
    Pour moi la conclusion est: utilisation de vector avec vector::reserve au début. A noter que la STL de Visual n'accroit pas la taille d'un vecteur de 1 mais de 50% de la capacité précédente, évitant des allocations répétées lors de l'ajout successif d'éléments, mais au détriment d'un ajustement mémoire amoindrit.

  20. #20
    Membre éclairé Avatar de vanitom
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    327
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 327
    Par défaut
    Ok là maintenant c'est d'enfer dans le fonctionnement et les performances.
    C'est vraiment cool de m'avoir aider comme ça.

    Par contre, j'aurais une dernière question.

    Je rappelle que je veux créer une liste générique permettant de gérer correctement le tri ascendant et descendant avec un nombre assez important de ligne.
    Je peux avoir autant de colonne qu'on veut.

    Pour que ça fonctionne j'ai fait un code crade.
    Pour personnaliser la méthode de tri, j'ai créer des fonctions (ou foncteurs) Predicate. Une pour le tri par texte et une pour le tri par nombre.
    Dans ces Predicate, je récupére 2 TknoListCtrlRow. Par contre je ne connais pas le numéro de la colonne pour récupérer le texte pour ensuite faire la comparaison. C'est la même chose pour savoir si je suis en tri ascendant ou descendant.
    J'ai donc créer des variables statique pour connaitre toutes ces informations. Mais je trouve ça dégeulasse et dangereux. Par exemple si deux listes se tri en même temps.

    Mais je ne sais pas comment faire autrement. Si vous avez une idée pour un arriver. Merci

    PS : Voici le code d'un de mes Predicate.

    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
    58
    59
     
    class TknoListCtrlEx :
    	public TknoListCtrl
    {
    [...]
    	struct SortBase {
    		public:		
    			static int				m_nCol;
    			static BOOL				m_bAsc;
    	};
     
    	struct SortByText : public SortBase
    	{
    		bool operator ()(TknoListCtrlRow& rRow1, TknoListCtrlRow& rRow2)
    		{
    			TknoListCtrlCell* pCell1 = rRow1.GetCellCol ( m_nCol );
    			TknoListCtrlCell* pCell2 = rRow2.GetCellCol ( m_nCol );
     
    			if ( !pCell1 || !pCell2 ) 
    			{
    				ASSERT ( FALSE );
    				return false;
    			}
     
    			if ( m_bAsc == TRUE )
    				return ( _tcscmp ( pCell1->GetText ( ), pCell2->GetText ( ) ) > 0 ) ? true : false;
    			else
    				return ( _tcscmp ( pCell1->GetText ( ), pCell2->GetText ( ) ) > 0 ) ? false : true;
    		}
    	};
     
    	struct SortByNumeric : public SortBase
    	{
    		bool operator ()(TknoListCtrlRow& rRow1, TknoListCtrlRow& rRow2)
    		{
    			TknoListCtrlCell* pCell1 = rRow1.GetCellCol ( m_nCol );
    			TknoListCtrlCell* pCell2 = rRow2.GetCellCol ( m_nCol );
     
    			if ( !pCell1 || !pCell2 ) 
    			{
    				ASSERT ( FALSE );
    				return false;
    			}
     
    			char strTemp[2000];
     
    			WideCharToMultiByte ( CP_ACP, 0, pCell1->GetText ( ), -1, strTemp, 2000, NULL, 0 );
    			double dValue1 = atof ( strTemp );
     
    			WideCharToMultiByte ( CP_ACP, 0, pCell2->GetText ( ), -1, strTemp, 2000, NULL, 0 );
    			double dValue2 = atof ( strTemp );
     
    			if ( m_bAsc == TRUE )
    				return ( dValue1 < dValue2 ) ? false : true;
    			else
    				return ( dValue1 < dValue2 ) ? true : false;
    		}
    	};
    }

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Tri rapide d'une grille (TStringGrid)
    Par Pierre Castelain dans le forum Codes sources à télécharger
    Réponses: 1
    Dernier message: 01/02/2013, 09h08
  2. Réponses: 13
    Dernier message: 25/04/2012, 18h04
  3. [MFC] surbrillance de ligne dans une CListCtrl
    Par Yoshette dans le forum MFC
    Réponses: 4
    Dernier message: 15/04/2005, 16h09
  4. Tri rapide
    Par DBBB dans le forum Algorithmes et structures de données
    Réponses: 11
    Dernier message: 10/12/2004, 17h54
  5. Selectionner ligne dans une ClistCtrl
    Par fr66 dans le forum MFC
    Réponses: 2
    Dernier message: 03/05/2004, 14h58

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