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 :

stack ou queue ?


Sujet :

C++

  1. #1
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Israël

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2017
    Messages : 34
    Par défaut stack ou queue ?
    Bonjour,

    J'ai besoin d'utiliser un conteneur et je m'interroge au niveau de la rapidité de traitement. Lequel serait le meilleur ?

    A la base j'hésitais entre stack et queue en ayant l'impression que stack serait plus rapide.

    Mais après réflexion je me demande si les deux ne sont pas en fait tout aussi lents puisqu'ils ne sont que des adaptateurs et non pas en eux mêmes des conteneurs.
    Et alors tant qu'a faire autant utiliser un vector...

    Je précise que le seul paramètre qui me préoccupe est la rapidité de traitement et qu'un LIFO ou FIFO ou autre forme d'accès m'est (dans ce cas) indifférent.

    Merci.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Salut,

    vector devrait toujours être le container par défaut.
    Cela dit il faudrait au moins décrire ce traitement pour savoir lequel serait mieux ou comment le faire mieux.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    stack<> est par défaut implémenté au dessus de vector<>, alors que queue<> est au dessus de deque<>.
    Celui qui ira le plus vite, c'est celui qui correspond à ton besoin. Et si tu as besoin d'une queue<>, utiliser une queue<> ou un deque<> sera aussi optimum, et il faudra vraisemblablement éviter le vector<> dans ce cas.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Si la seule chose qui t'intéresse, c'est la rapidité d'accès aux éléments, sans ajouts, sans retraits, alors, la question ne se pose pas: il te faut un tableau.

    Cela pourrait cependant impliquer une certaine baisse (et même une baisse certaine dans le pire des cas) des performances au moment de remplir ta collection. Il vaut donc mieux en être conscient

    De même, la recherche peut, dans le meilleur des cas, se faire en O(log(N) ), si les éléments sont correctement tirés, mais pourrait s'étendre à du O(N) dans le cas contraire, et l'unicité des éléments n'est absolument pas garantie.

    Si tu passe ton temps à ajouter / retirer des éléments (sans commencer à les chercher), la liste sera sans doute pour toi.

    Si tu passes d'avantage de temps à chercher un élément particulier parmi "tant d'autres", le tableau trié est l'idéal, mais, à défaut de pouvoir garantir le tri, les structures basées sur les arbres binaires seront tes amies.

    Pile et file (stack et queue) posent de très sérieux problèmes en terme d'accès aux éléments, ce qui justifie d'ailleurs leur nom:
    • dans une pile, tu ne peux pas accéder à un élément avant d'avoir retiré tous les éléments qui ont été ajoutés après celui auquel tu veux accéder
    • dans une pile, tu ne peux accéder à un élément qu'après avoir retiré ceux qui ont été ajouté avant celui auquel tu veux accéder.

    LIFO et FIFO ne sont donc pas que des concepts! Ce sont bel et bien des notions qui viennent avec des notions dont il faut tenir compte. Il est particulièrement rare de se trouver dans une situation dans laquelle l'ordre dans lequel tu accèdes à tes données n'a absolument aucune importance
    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 actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Israël

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2017
    Messages : 34
    Par défaut
    Merci à tous de votre participation,

    En fait mon besoin est le suivant : ayant un programme avec un certain nombre de fonctions qui peuvent se renvoyer les une aux autres, il y a une forme de désordre qui s'installe, des appels nombreux et incontrolés. Qui plus est, je crains de que l'application ne tombe un jour dans une boucle infinie. Je cherche donc à neutraliser cette liberté qu'ont les fonctions à s'appeler, et à créer à la place une "liste d'attente". De telle sorte qu'une fonction lorsqu'elle devrait en appeler une autre, inscrive au lieu de cela sa demande dans la liste d'attente, et le programme 'main' se chargera plus tard de faire les appels.
    Notons que l'ordre de traitement des données n'a pas d'importance, pour peu qu'elles soient toutes bien traitées.
    La vitesse de traitement, elle par contre, est cruciale.
    Je cherche donc quel est le meilleur moyen de créer cette liste, sachant que je vais devoir très souvant y ajouter et en retirer des éléments (et que même lorsque je suis en train d'en retirer, d'autres vont s'y ajouter) , mais que l'ordre n'a aucune importance.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Oui, donc, tu vas passer ton temps à ajouter et à supprimer des éléments...

    A priori, les tableaux ne sont donc pas pour toi

    Par contre, pile, file, liste et éventuellement std;;deque s’avéreront sans doute intéressante. Pile, file et liste proposent l'ajout et la suppression en temps constant, alors que deque ne fourni cela que pour les éléments qui se trouve "en fin de collection".

    J'aurais même tendance à dire que la file (d'attente) serait sans doute l'idéal étant donné:
    • que l'on ajoute les éléments d'un coté
    • que l'on retire les éléments de l'autre
    • que l'ordre des éléments est maintenu (FIFO)

    parce que,tu m'excuseras,mais, quand tu dis
    Notons que l'ordre de traitement des données n'a pas d'importance, pour peu qu'elles soient toutes bien traitées.
    hé ben, j'ai le plus grand mal à te croire

    Je peux en effet me tromper, mais, généralement, l'ordre d'exécution de différentes fonctions va grandement influer sur le résultat final et il est même possible d'envisager des circonstances où un ordre d'exécution erroné peut carrément empêcher certaines actions d'être entreprises.

    Le seul cas où l'ordre pourrait effectivement n'avoir aucune importance, serait que chaque fonction appelée travaille sur des données strictement différentes et sans aucun lien entre elles. C'est envisageable, mais relativement rare

    Ceci étant dit, je crois que tu fais fausse route en voulant placer tes fonctions en file d'attente.

    A mon sens, cela ne résoudra rien, du moins, pour le problème que tu essaye de gérer: si A fait appel à B, que B fait appel à C et que C fait appel à A, tu auras beau mettre tes fonctions en file d'attente, C finira toujours par faire appel à A, quoi qu'il arrive, et la boucle sera bouclée.

    Tu aurais intérêt réfléchir à ton problème comme à un cas de récursivité; c'est à dire, en définissant le cas de base: qu'est ce qui pourra faire, dans ma boucle A, B, C, que la "fonction suivante" ne sera pas appelée, et que la boucle s'arrête Ensuite, il faudra tout faire pour "tendre" vers ce cas particulier.

    Maintenant, si chaque fonction ne doit jamais être appelée plus d'une (ou de X ) fois (mais est-ce le cas ) tu peux envisager d'avoir un "élément extérieur" qui pourrait s'occuper de "garder une trace" des différentes fonctions qui ont été appelées.

    Pour chaque fonction à laquelle tu ferait appel, tu commencerais par vérifier si la fonction a déjà été appelée (aussi souvent qu'elle le pouvait) ou non, et tu n'y ferais appel que... si ce n'est pas le cas.

    Seulement, une telle vérification "prendra du temps"... Peut-être pas "énormément", mais sans doute assez pour ressentir une baisse de performances

    Au final, si j'étais toi, j’achèterais sans doute une grande nappe en papier, et je commencerais à tracer le diagramme d'appel des fonctions dessus: si A appelle B, je tracerais une flèche partant de A allant jusqu'à B.

    Une fois que j'aurais ce diagramme, je regarderais où se situent les éventuelles boucles, et je verrais comment je peux faire pour les supprimer
    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

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Des tableaux utilisés intelligemment peuvent faire l'affaire.
    Si tu reserve ton vector avec une taille suffisante, sans être abusive, push dessus depuis plusieurs threads (avec un lock bien sûr), et swap son contenu dans un autre sur le thread qui va faire les opérations, ca te fait une FIFO efficace et un cache-miss limité puisque tableau et tu évites l'inconvénient de retirer un élément en tête, ce qui est le plus gros piège et l'opération la plus lente du vector imo.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  8. #8
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2017
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Israël

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2017
    Messages : 34
    Par défaut
    @Bousk

    push dessus depuis plusieurs threads (avec un lock bien sûr), et swap son contenu dans un autre sur le thread qui va faire les opérations
    Très bon, je n'avais pas pensé à avoir recours au multi threading, mais bon le gain n'est peut être pas énorme... A vérifier.

    ca te fait une FIFO efficace
    Vous voulez dire une LIFO, non ?

    @Koala01

    Au final, si j'étais toi, j’achèterais sans doute une grande nappe en papier, et je commencerais à tracer le diagramme d'appel des fonctions dessus: si A appelle B, je tracerais une flèche partant de A allant jusqu'à B.
    C'est justement après avoir fait ça (bon, pas sur une nappe, je me suis modestement contenté d'une feuille A4, mais avec les flèches et tout le reste) que je suis arrivé à cette conclusion.
    L'idée est que toutes les fonctions travaillent dans le même but, mais en employant des moyens différents, quand l'objectif est d'arriver à un certain résultat.
    C'est un programme compliqué à expliciter, mais imaginons l'équivalent dans un jeu : il y a un méchant monstre qu'il faut tuer, on peut le frapper à l'épée, l'étrangler, ou même par exemple bruler l'oxygène de la pièce pour qu'il ne respire plus etc...
    Chaque coup infligé a des répercussions directes et indirectes, si par exemple je lui ai donné un coup de poing, à part le coup qui l'affaiblit, sa respiration devient également un peu plus difficile, et si paralellement il ne reste plus assez d'oxygène dans la pièce, cela peut être fatal, ou pas . Ou bien plus subtil, il peut d'ores et déjà ne plus avoir la force de supporter le coup d'épée qu'il avait reçu au tour précédent.
    Donc quand dans le "main" un coup lui est donné, tout un engrennage (plus complexe et surtout avec une quantité beaucoup plus grande d'éléments que ce que je viens de décrire) se met en marche. Ce sont les fameuses fonctions qui vont ici calculer si le coup est fatal ou non.
    Le principal est la réponse à cette question (coup fatal ou pas), l'ordre de traitement n'importe pas puisque tout est le résultat d'un seul et même coup.
    Par contre il faut vite calculer, avant le coup suivant... Et il ne faut pas non plus épuiser la pile dans laquelle les fonctions s'inscrivent les unes derière les autres...

    C'est la raison pour laquelle j'ai pensé à cette file d'attente.

    A mon sens, cela ne résoudra rien, du moins, pour le problème que tu essaye de gérer: si A fait appel à B, que B fait appel à C et que C fait appel à A, tu auras beau mettre tes fonctions en file d'attente, C finira toujours par faire appel à A, quoi qu'il arrive, et la boucle sera bouclée.
    C'est à dire que les fonctions ne font plus d'appel direct (et donc automatique), mais inscrivent leur appel dans la liste, et là bas il est plus facile d'installer un "controleur" qui décide si oui ou non donner suite à cet appel, en fonction de ce qui aura déjà été fait.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Hmm, si tu n'as pas plusieurs threads, je pense que tu as juste une mauvaise architecture alors..
    Citation Envoyé par Legro Voir le message
    l'équivalent dans un jeu : il y a un méchant monstre qu'il faut tuer, on peut le frapper à l'épée, l'étrangler, ou même par exemple bruler l'oxygène de la pièce pour qu'il ne respire plus etc...
    Chaque coup infligé a des répercussions directes et indirectes, si par exemple je lui ai donné un coup de poing, à part le coup qui l'affaiblit, sa respiration devient également un peu plus difficile, et si paralellement il ne reste plus assez d'oxygène dans la pièce, cela peut être fatal, ou pas . Ou bien plus subtil, il peut d'ores et déjà ne plus avoir la force de supporter le coup d'épée qu'il avait reçu au tour précédent.
    Oui mais ce n'est pas le coup d'épée qui déclence la mort par manque d'oxygène.
    Le coup d'épée il fait son truc, met à jour l'état du machin, puis tu exécutes la mise à jour de la pièce, puis tu passes à l'application du process de l'oxygène, puis tu vérifies sa mort. Et chaque étape est indépendante, et surtout chaque étape ne déclenche pas l'étape suivante, c'est juste une suite de processus indépendants. Ca évite, entre autre, ton problème initial.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Legro Voir le message
    @Bousk
    Vous voulez dire une LIFO, non ?
    Tout dépend de l'ordre dans lequel tu traitera les différents éléments :
    si tu les traites dans l'ordre "premier arrivés, premiers traités" c'est FIFO, si tu les traites dans l'ordre "dernier arrivé, premier traité", c'est LIFO
    Le principal est la réponse à cette question (coup fatal ou pas), l'ordre de traitement n'importe pas puisque tout est le résultat d'un seul et même coup.
    Oui, mais non... Je suis tout à fait d'accord avec Bousk sur ce coup là...: ce n'est pas au coup de poing ou au coup d'épée de décider de virer l'oxygène de la pièce: c'est à ... un sors qui aura cet effet là, et donc, il appartiendra à... celui qui connaît ce sort de l'invoquer...

    De plus, mettons que cinq personnes attaquent ton super-méchant en même temps.

    Chaque attaque peut être fatale "à elle seule"... ou pas... Et donc, il y a une question qui se pose:

    Mettons que la deuxième attaque portée (comprends: prise en compte) soit fatale, que va-t-il se passer au niveau des attaques n° 3, 4 et 5 (celles qui n'ont pas encore été prises en compte) Vont-elles être lancées sur le corps de notre défunt ennemi "parce qu'elles étaient programmées" ou vont-elle "simplement" être annulées, parce que, ben, il est mort, on ne pourra pas le tuer une deuxième fois

    Et nous en revenons toujours au même point: la deuxième attaque prise en compte n'a peut-être été fatale que... parce que la première avait déjà fortement (ou du moins: suffisamment) diminué la résistance de l'ennemi. S'il n'y avait eu que la deuxième attaque, elle aurait tout aussi bien pu ne pas être fatale!

    Maintenant, je ne fais que suivre la logique de l'exemple que tu me donnes, car je ne suis pas capable de regarder au dessus de ton épaule pour voir dans quelle situation réelle tu te trouves. Peux être que si tu nous expliquais exactement le projet sur lequel tu travailles, nous aurions plus facile à t'orienter vers une solution adéquate

    Mais, quelle que soit la manière dont tu tournes les choses, telles que tu nous les as présentées, je reste sur mon point de vue: tu fais fausse route du tout au tout pour l'instant
    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

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Gérer les queue avec sql server ?
    Par devdev dans le forum MS SQL Server
    Réponses: 8
    Dernier message: 17/06/2004, 17h38
  2. Differences Stack et Heap
    Par elsargento dans le forum C++
    Réponses: 9
    Dernier message: 26/05/2004, 16h10
  3. [Exception] récupération de la stack trace d'une Throwable
    Par totof2308 dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 14/05/2004, 14h49
  4. [Optimisation] Hardware Matrix Stack
    Par Blustuff dans le forum OpenGL
    Réponses: 6
    Dernier message: 05/02/2004, 13h45
  5. Stack overflow
    Par portu dans le forum Langage
    Réponses: 3
    Dernier message: 26/11/2003, 15h16

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