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

Langage Delphi Discussion :

Tri de chaînes de caractères : Optimiser vitesse ?


Sujet :

Langage Delphi

  1. #41
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    A propos de
    au lieu de chercher min/max tu remplies au départ le tableau avec des "-1" pour indiquer des indices invalides, et après l'algo de tri tu supprimes les "-1" qui restent:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    j := 0;
    for i := 0 to max do
    begin
      if Indexes[i] >= 0 then << au départ le tableau est rempli avec des "-1" donc la boucle ne fait rien
      begin
        Indexes[j] := Indexes[i];
        Inc(j);
      end;
    end;
    Il y a un truc qui coince dans l'explication ???.

    A+.

  2. #42
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 457
    Points
    28 457
    Par défaut
    Citation Envoyé par Gilbert Geyer Voir le message
    Re-bonjour,

    A propos de
    Il y a un truc qui coince dans l'explication ???.

    A+.
    ...hum...je crois que je me suis un peu trompé dans mes explications

    dans ma tête tu renseignais IndexesOrdreTri[Cara] pour Cara de CaraMin à CaraMax, mais en fait ça n'a rien à voir

    bref, ta boucle qui détermine CaraMin..CarMax n'apporte rien à la procédure puisqu'au lieu de limiter le parcours de la liste tu multiplies ce parcours.

    Avec une liste [#0..#255] tu gères tous les cas de figure puis tu cherches dans cette liste ce qui a été renseigné (ça fait 2 boucles), alors qu'avec CaraMin et CaraMax, tu vas parcourir la liste DonneesTxt autant de fois que CaraMax-CaraMin, pour ne traiter qu'un seul caractère à chaque boucle. C'est une fausse bonne idée.

  3. #43
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    Paul TOTH : ...hum...je crois que je me suis un peu trompé dans mes explications

    dans ma tête tu renseignais IndexesOrdreTri[Cara] pour Cara de CaraMin à CaraMax, mais en fait ça n'a rien à voir
    C'est pas grave, on peut se tromper.

    bref, ta boucle qui détermine CaraMin..CarMax n'apporte rien à la procédure puisqu'au lieu de limiter le parcours de la liste tu multiplies ce parcours.

    Avec une liste [#0..#255] tu gères tous les cas de figure puis tu cherches dans cette liste ce qui a été renseigné (ça fait 2 boucles), alors qu'avec CaraMin et CaraMax, tu vas parcourir la liste DonneesTxt autant de fois que CaraMax-CaraMin, pour ne traiter qu'un seul caractère à chaque boucle. C'est une fausse bonne idée.
    En fait c'est surtout CaraMin qui me permet de caler IndexesOrdreTri[i] sur l'indice i = 0 lors d'un tri croissant.
    Lors du tri sur le premier caractère je parcours effectivement la liste DonneesTxt autant de fois que CaraMax-CaraMin.
    Pour les tris sur les caractères suivants je cherche à ne parcourir que des sous-listes de DonneesTxt.
    En tous cas pour l'instant je n'ai pas trouvé d'autre idée pour obtenir IndexesOrdreTri[i] sans trier les chaînes elles-mêmes.

    Ce qui m'encourage poursuivre cette piste ce sont les résultats des tests de vitesse de mon message du 16/10/2013 12h29 :
    A) Pour Profondeur tri = 1 :
    - Tri de 2000000 Lignes de 250 caractères = 500000000 avec Tri_Str_Indexes en 94 ms (Hors affichage du résultat)
    - Tri de 2000000 Lignes de 250 caractères = 500000000 avec Tri_Casiers2_StrArray en 374 ms (Hors affichage du résultat) : 3,97 fois plus lent

    B) Pour Profondeur tri = 250 :
    - Tri de 2000000 Lignes de 250 caractères = 500000000 avec Tri_Casiers2_StrArray en 1123 ms (Hors affichage du résultat)
    Je ne pense pas pouvoir conserver le facteur de gain de 3,97 mais si j'en obtiens un d'au moins 2 j'en serai bien content...Y'a plus qu'à ... Cela ne coûte que du temps pour essayer.

    A+.

  4. #44
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    Au final j'ai abandonné ma piste car elle complique beaucoup trop le tri sur les caractères suivants pour obtenir un gain de vitesse.

    Entre-temps j'ai failli mettre Tri_Casiers2 à la poubelle vu qu'elle s'est avérée être 2 fois plus lente que Tri_Casiers3_Str(var DonneesTxt: tStringList; ...) dont la var en rose m'avait laissé penser qu'elle renvoyait aussi la liste triée en plus des Indexes de l'ordre trié. Donc Tri_Casiers2 est à conserver pour ce type de besoin.

    Et pour ce qui est de Tri_Casiers3 je l'ai modifiée comme suit pour y alimenter directement la var IndexesOrdreTri au lieu de passer par la variable locale intermédiaire Indexes (mais sa vitesse reste inchangée) :

    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
    type tAOI = array of integer;
    
    procedure Tri_Casiers3_StrBis(const DonneesTxt: tStringList; ProfMaxTri: integer; TriCroissant: boolean; var IndexesOrdreTri: tAOI);
    type
      PStringItem = ^TStringItem;
      TStringItem = record
        Value: PChar;
        Index: Integer;
        Next: PStringItem;
      end;
      TCharList = array[#0..#255] of PStringItem;
    
      procedure FillList(var Index: PInteger; Delta: Integer; const Items: TCharList; CharPos: Integer);
      var
        SubList: TCharList;
        FirstChar: Char;
        NthChar: Char;
        Item: PStringItem;
        Next: PStringItem;
        SensDeTri: shortInt;
      begin
        for FirstChar := #0 to #255 do
        begin
          Item := Items[FirstChar];
          if Item = nil then Continue;
          if Item.Next = nil then
          begin
            Index^ := Item.Index;
            Inc(Index, Delta);
            Continue;
          end;
          FillChar(SubList, SizeOf(SubList), 0);
          repeat
            Next := Item.Next;
            Inc(Item.Value);
            if (CharPos > ProfMaxTri) or (Item.Value^ = #0) then
            begin
              Index^ := Item.Index;
              Inc(Index, Delta);
            end else begin
              NthChar := Item.Value^;
              Item.Next := SubList[NthChar];
              SubList[NthChar] := Item;
            end;
            Item := Next;
          until Item = nil;
          FillList(Index, Delta, SubList, CharPos + 1);
        end;
      end; // FillList
    
    var
      AllItems: array of TStringItem;
      FirstList: TCharList;
      Index: Integer;
      Count: Integer;
      Str: string;
      FirstChar: Char;
      Item: PStringItem;
      Delta: Integer;
      //Indexes: array of Integer;
      Idx: PInteger;
    begin
      SetLength(AllItems, DonneesTxt.Count);
    
      FillChar(FirstList, SizeOf(FirstList), 0);
      Count := 0;
      for Index := 0 to DonneesTxt.Count - 1 do
      begin
        Str := DonneesTxt[Index];
        if Str <> '' then
        begin
          Inc(Count);
          Item := @AllItems[Index];
          Item.Value := Pointer(Str);
          Item.Index := Index; // Index dans la tableau
          FirstChar := Item.Value^;
          Item.Next := FirstList[FirstChar];
          FirstList[FirstChar] := Item;
        end;
      end;
    
      //SetLength(Indexes, Count);
      SetLength(IndexesOrdreTri, Count);
    
      {if TriCroissant then
      begin
        Idx := @Indexes[0];
        FillList(Idx, +1, FirstList, 2)
      end else begin
        Idx := @Indexes[Count - 1];
        FillList(Idx, -1, FirstList, 2);
      end; }
    
      if TriCroissant then
      begin
        Idx := @IndexesOrdreTri[0];
        FillList(Idx, +1, FirstList, 2)
      end else begin
        Idx := @IndexesOrdreTri[Count - 1];
        FillList(Idx, -1, FirstList, 2);
      end;
    end; // Tri_Casiers3_StrBis
    A+.

  5. #45
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Re-bonjour,

    Juste une petite rectification : j'avais dit queTri_Casiers2 s'est avérée être 2 fois plus lente que Tri_Casiers3_Str, en fait ce n'est vrai que lors d'un tri sur seulement le premier caracatère :
    A) Pour profondeur de tri = 1
    - Tri de 2000000 Lignes de 250 caractères = 500000000 avec Tri_Casiers2_Str (StringList) en 437 ms (Hors affichage du résultat)
    - Tri de 2000000 Lignes de 250 caractères = 500000000 avec Tri_Casiers3_StrBis (StringList + IndexesOrdreTri) en 219 ms (Hors affichage du résultat)

    B) Pour profondeur de tri = 250
    - Tri de 2000000 Lignes de 250 caractères = 500000000 avec Tri_Casiers2_Str (StringList) en 936 ms (Hors affichage du résultat)
    - Tri de 2000000 Lignes de 250 caractères = 500000000 avec Tri_Casiers3_StrBis (StringList + IndexesOrdreTri) en 734 ms (Hors affichage du résultat)
    Pour un tri sur tous les caractères l'écart se réduit.

    A+.

  6. #46
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    Rectification d'une erreur : Dans mon message du 08/10/2013, 12h23 j'avais dit que QuickSort Recursif était 3006 fois plus lent que Tri_Casiers2_Str. En fait ce 3006 est exagéré et vu son extrême lenteur je n'avais pas refait des tests, donc voici le rectificatif :
    Pour profondeur de tri = 250 :
    - Tri de 100000 Lignes de 250 caractères = 25000000 avec Tri_Casiers2_Str (StringList) en 47 ms (Hors affichage du résultat)
    - Tri de 100000 Lignes de 250 caractères = 25000000 avec Tri_Casiers3_StrBis (IndexesOrdreTri) en 31 ms (Hors affichage du résultat)
    - Tri de 100000 Lignes de 250 caractères = 25000000 avec QuickSort Recursif en 10312 ms (Hors affichage du résultat)
    Donc QuickSort Recursif :
    - 219 fois plus lent que Tri_Casiers2_Str (au lieu des 3006 !!!)
    - et 332 fois plus lent que Tri_Casiers3_StrBis
    Ceci n'empêche toutefois pas le fait qu'une fois qu'on a goûté à la vitesse du Tri-Casiers on trouve le QuickSort interminablement lent.

    A+.

  7. #47
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 586
    Points : 25 262
    Points
    25 262
    Par défaut
    Très intéressant votre échange à tous les deux !
    J'ai souvenir d'un vieux sujet sur le dédoublonnage, j'ai survolé vos réponses, j'aurais bien participé mais vraiment pas le temps !

    L'algo IndexesOrdreTri finalement est proche de celui de Suppression de doublons avec ce système de tableau d'index !

    Pour le moment, mon volume des données est faible (quelques milliers de lignes) dont la TStringList en Sorted est largement suffisante
    Au besoin, je comparerais avec la THashedStringList

    Je préfère utiliser des trucs standards et pas trop d'algo maison lorsque je fournis un travail pour mon employeur, moins performant mais plus maintenable !

    Dans mon algo, les chaines s'ajoutent au fur et à mesure lors de la découpe du Stream CSV, l'ordre n'a pas d'importance, ce qui compte c'est les doublons !
    Je testerais IndexesOrdreTri et SupprDoublonsAOS si j'ai le temps

    Si l'on trie tout à la fin, si il y a bcp de doublons (mon cas), cela occupe bcp de mémoire pour rien
    Si l'on trie en cours de route plus économique en mémoire mais plus lent

    Merci à vous deux !

  8. #48
    Modérateur

    Homme Profil pro
    Ingénieur retraité
    Inscrit en
    Octobre 2005
    Messages
    2 396
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur retraité

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 396
    Points : 3 266
    Points
    3 266
    Par défaut
    Bonjour,

    ShaiLeTroll : L'algo IndexesOrdreTri finalement est proche de celui de Suppression de doublons avec ce système de tableau d'index !
    Absolument d'accord et les vitesses d'exécution sont du même ordre.
    Pour ma part j'ai retenu comme leçon du problème de la suppression de doublons qu'il ne faut surtout rien "supprimer" dans la liste fournie en entrée mais juste y repérer les doublons et les "ignorer" lors de l'alimentation de la Liste-Resultat, si on cherche du gain de vitesse.

    Je préfère utiliser des trucs standards et pas trop d'algo maison lorsque je fournis un travail pour mon employeur, moins performant mais plus maintenable !
    Cela se comprend fort bien, car la maintenance d'un algo maison, si elle est facile pour celui qui l'a conçu, l'est beaucoup moins pour quelqu'un d'autre.

    A+.

+ Répondre à la discussion
Cette discussion est résolue.
Page 3 sur 3 PremièrePremière 123

Discussions similaires

  1. Tri de chaîne de caractére
    Par lekaf974 dans le forum Langage
    Réponses: 6
    Dernier message: 19/03/2013, 01h07
  2. Tri de chaînes de caractères
    Par zizou.r23 dans le forum Débuter
    Réponses: 4
    Dernier message: 11/02/2013, 11h56
  3. [XL-2007] Mise en rouge et en gras d'un chaîne de caractère / optimisation
    Par FanTasTik dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 29/08/2012, 16h48
  4. Tri de chaîne de caractère
    Par sk8trasher dans le forum Débuter
    Réponses: 12
    Dernier message: 28/06/2012, 08h00
  5. tri par corrélation entre chaînes de caractères
    Par petitmic dans le forum Langage SQL
    Réponses: 7
    Dernier message: 09/09/2005, 15h15

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