CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

une SList

m-2
m-2
Niveau 10
27 septembre 2006 à 13:59:18

voila on est en train de faire une liste simplement lié (ou liste chainé) comme celle de la bilbiothèque de c++ (même fonction, meme nom, meme parametre) et j´ai quelque misere avec la fonction insert... mais je vous explique d´abord les grandes lignes..

donc dans notre Slist, on a deux champ, la premiere étant la donné (m_donnée) et la deuxieme étant un pointeur sur la prochaine donnée (m_pSuiv) , on garde en mémoire un pointeur sur le début de la liste, un pointeur sur le dernier élément ainsi que le nombre d´élément dans la liste.

pour parcourir la liste, on se sert D´iterateur qui pointe sur l´élément précédent celui qu´on veut avoir (par exemple, si j´ai une liste avec "4, 5, 6, 7, 8" et que je veux l´élément "8", l´iterateur pointe sur le "7"), on a également un bool dans la classe iterateur qui nous dit si l´élément pointé est le premier de la liste ou non (vu qu´il n´y a pas d´élément précédent, l´adresse du pointeur sera alors exactement la bonne et non celle du précédent) et lorsque l´on arrive à la fin, le pointeur (m_pSuiv) est null

voici donc une petit résumé de ma fonction insert:

void insert(p_donné, p_itérateur)
{
if (++m_nbElements == 1) // pour ajouter dans une
liste vide

if (p_itérateur == m_pTete) // pour ajouter au déb
ut de la liste

if (p_itérateur == m_pQueue) //pour ajouter a la f
in de la liste

..... // pour ajouter quelque part au milieu
}

ca marche très bien pour tout sauf dans un cas: lo
rsqu´il n´y a qu´un seul élément dans la liste, l´itérateur pointe nécessairement sur la tete et la queue de la liste en meme temps.. vous voyez le bug? dès qu´il entre dans la fonction insert, il ira tout simplement dans la premiere condition qu´il trouvera sur son chemin et non dans la condition qu´il lui faut.. j´ai penser rajouter une condition du genre "if (m_nbElements == 1)" mais je sais pas vraiment quoi mettre dedans..

bref, je sais pas vraiment si j´ai été clair et si ma question a du sens mais bon.. c´est le plus court que j´ai pu faire!

godrik
godrik
Niveau 30
27 septembre 2006 à 14:05:50

Si ta liste est simplement chainé, tu n´a pas besoin de stocker le derniere element ? (ou il y a une subtilité que je n´ai pas suivit ?)

Fvirtman
Fvirtman
Niveau 10
27 septembre 2006 à 14:07:31

Tu as 2 façons de gérer cela :

- soit tu gardes la façon dont tu fais les choses, et il te faut considérer les cas particuliers.

- soit tu appliques la méthode de la "sentinelle"
--> un maillon de plus (qui pointe sur lui meme), que tu mets en fin de maillon.

Ainsi, ta liste n´est jamais vide (un cas particulier de moins) y´a au moins la sentinelle.
Ton pointeur fin pointe sur la sentinelle de façon a ce que tu puisses itérer avec :

for(i=begin();i!=end();i.incremente())

et le seul cas ou les 2 pointeurs begin et end pointent au meme endroit, c´est quand la liste est vide (ils pointent tous les deux sur la sentinelle)

ça te rajoute un element, mais ta liste contient beaucoup moins de cas particuliers. Et les STL (std::slist et std::list) sont gérés comme ça :-)

m-2
m-2
Niveau 10
27 septembre 2006 à 16:50:56

godrik: on garde un pointeur sur la fin de la liste en tout temps, histoire de ne pas reparcourir la liste a chaque fois qu´on fait un .end()

Fvirtman: la est le probleme, on doit garder cette structure de liste (c´est un exercice dans mon cours d´info), c´est-à-dire que la liste peut etre vide et le dernier élément a un pointeur null.. l´élément "bidon" à la fin de la liste est représenté par ce pointeur null

le gros du probleme, c´est que je ne peux pas comparer l´itérateur à m_pTete ou m_pQueue puisque les deux sont vrais parce qu´ils pointent sur la meme donnée...

Fvirtman
Fvirtman
Niveau 10
27 septembre 2006 à 17:03:48

Alors :
- Ajouter une sentinelle ne nécessite pas de changer tes structures.

Sinon, si tu ne veux pas de sentinelle :
- Le but d´une liste simplement chainée n´est pas de stocker le dernier élément. Je pense que ton pointeur "end" t´encombre si tu ne geres pas de sentinelle.
Pourquoi aurais tu besoin sans arret d´un pointeur sur le dernier élément ? celui ci est + sollicité que les autres ?
Tester que c´est le dernier élément revient juste a tester que le pointeur "suivant" est a NULL.

"le gros du probleme, c´est que je ne peux pas comparer l´itérateur à m_pTete ou m_pQueue puisque les deux sont vrais parce qu´ils pointent sur la meme donnée... "

--> ?
un itérateur est "vrai" ?
Comparer l´itérateur d´une liste chainée, c´est simplement comparer les adresses qu´ils pointent, c´est tout !

Si tu consideres m_pTete et m_pQueue comme des pointeurs, le simple teste m_pQueue == m_pTete te permet de savoir si ces pointeurs montrent le meme élément !
Mais je suis convaincu que dans une liste simplement chainée, tu n´as pas besoin de m_pQueue...

m-2
m-2
Niveau 10
27 septembre 2006 à 17:13:03

un pointeur sur le dernier élément sert a renvoyer.. le dernier élément! sinon, dans la fonction .end(), faudrait refaire la liste à partir du début simplement pour renvoyé le dernier élément? et s´il y a 3 millions d´éléments? ca risque d´etre long!

l´iterateur est "vrai" lorsque l´adresse pointé par celui-ci est égal à l´adresse de m_pTete ou m_pQueue.. lors du test (it == m_pTete), cette comparaison renvoie nécessairement vrai ou faux... tu pige? donc dans le cas ou ou it == m_pQueue == m_pTete, ceux-ci sont "vrai"... faut vraiment s´expliquer sur tout?!

le test m_pQueue == m_pTete permet de savoir s´il pointe sur le meme élément je suis bien d´accord, ceci dit, ca ne me dit pas si la donnée doit être inséré AVANT ou APRES la donnée pointé par m_pTete et m_pQueue!

godrik
godrik
Niveau 30
27 septembre 2006 à 17:14:22

Je suis d´accor que si tu veux respecter l´interface de la STL il faut pouvoir répondre a end().
mais pourquoi ne pas renvoyer NULL lors de cet appel?

m-2
m-2
Niveau 10
27 septembre 2006 à 17:18:50

la n´est pas le probleme..

Fvirtman
Fvirtman
Niveau 10
27 septembre 2006 à 17:26:23

Je trouve que tu te casses la tete pour rien.
"l´iterateur est "vrai" lorsque l´adresse pointé par celui-ci est égal à l´adresse de m_pTete ou m_pQueue"
--> normalement, un itérateur n´est ni "vrai" ni "faux", il est égal a end(), ou a begin() si tu veux, ou a autre chose...

"et s´il y a 3 millions d´éléments? ca risque d´etre long"
--> Je sais bien (crois moi, j´en ai bouffe des listes chainées), mais la ou je ne suis pas d´accord, c´est qu´il n´y a pas de réel intéret dans une slist de faire cela. Comme dit Godrik, fait juste que end() renvoie NULL dans ce cas la.
Ta fonction end() sert normalement uniquement a savoir si tu as atteint la fin de la liste, si un itérateur IT déja placé, donné, l´a atteint...
Dans le cas d´une slist, tu as juste struct::suivant == NULL pour définir qu´une liste est finie, il suffit de tester l´élément ou tu es et de regarder si le pointeur suivant est a NULL ou pas, ainsi, tu sauras si tu es sur end().

Voila, si tu as l´impression que je réponds a coté, ce n´est pas parce que je ne sais pas faire de slist (j´en ai bouffé des slist), c´est juste que je trouve que tu te compliques la vie pour une slist, et que dans cette vie compliquée, j´ai du mal a te suivre.

m-2
m-2
Niveau 10
27 septembre 2006 à 17:36:09

je suis sur que tu t´y connais assez, sinon je t´aurais meme pas poser la question..

mais relit mon deuxieme message... j´ai pas le choix de le faire comme ca, c´est un exercice à faire dans un cours, le prof nous a donné cette structure de liste et il nous as dit de la complété.. on sait très bien que ce n´est pas la seule et surtout la meilleure facon de faire une list, mais c´est comme ca qu´on doit la faire!

Fvirtman
Fvirtman
Niveau 10
27 septembre 2006 à 17:42:27

Bon, alors on va dire que ce dernier pointeur queue est obligatoire.
Si tu inseres un élément, tu l´inseres a la fin ?
Donc tu n´as qu´as te dire que si tu inseres un élément, tu l´inseres APRES le derniere élément.

Comme ça, tu te sers de ton dernier pointeur, tu crées un nouvel élément E;
tu remplis E.
tu mets Mqueue->suivant = E;
puis ensuite Mqueue = E; (pour bien remettre ton pointeur de fin sur le dernier élément)
Ainsi, tu gardes tout cohérent

Mais testes bien sur que Mqueue ne pointe pas sur NULL (liste vide)
si c´est le cas, tu crées une nouvelle liste et tu fous les 2 pointeurs (tete et queue) sur le meme et seul élément.

Pour l´insertion, il ne devrait pas y avoir de soucis ni de conflit avec Mtete, si tu inseres apres Mqueue (insertion en fin de liste)

godrik
godrik
Niveau 30
27 septembre 2006 à 17:44:17

ca ne fait jamais que 4 cas:
tu insere au début, ou en fin, ou ni l´un ni l´autre, ou les deux.

m-2
m-2
Niveau 10
27 septembre 2006 à 18:02:56

je vais faire une petite trace pour etre sur qu´on se comprend bien car je crois que j´ai pas été vraiment clair :P

disons que j´ajoute 2 et 6 dans la liste

a date, on a 4 cas (dans cette ordre dans la fonction insert) :
-ajout dans une liste vide if (++m_nbElement == 1)
-ajout a la tete if (it == m_pTete)
-ajout a la queue if (it == m_pQueue)
-ajout au milieu (par défaut à la fin)

alors quand je fait list.insert(2) il s´insère dans une liste vide, un pointeur est donc assigner à m_pTete et à m_pQueue (il est à la fois, au début et à la fin de la liste)
donc m_pTete pointe sur la donnée qui elle a un pointeur null

le probleme vient quand je fais list.insert(6), il passe par dessus la premiere condition (ajout dans une liste vide), il arrive donc a "if (it == m_pTete)" et s´insère a la tete car end() et begin() pointe sur la meme chose... donc dans la liste on obtient {6, 2}

et si on inverse les conditions (mettre m_pQueue avant m_pTete dans la fonction insert), on arrive au même résultat si on insère 2 et 6, on obtient {6, 2}

j´espere avoir été plus clair cette fois ci.. si non bah laisser tomber et j´attendrai à demain pour savoir :P

m-2
m-2
Niveau 10
27 septembre 2006 à 18:04:25

petite précision quand je disais

"- ajout au milieu (par défaut à la fin)"

je voulais dire a la fin de la fonction et non a la fin de la liste... car la liste doit etre en ordre..

Fvirtman
Fvirtman
Niveau 10
27 septembre 2006 à 18:12:23

Un exemple est déja + parlant.

je numérote tes cas :

1)ajout dans une liste vide if (++m_nbElement == 1)
2)ajout a la tete if (it == m_pTete)
3)ajout a la queue if (it == m_pQueue)
4)ajout au milieu (par défaut à la fin)

D´acc, donc si tu gardes tes conditions dans l´ordre donné, forcément, il tombe sur le cas "insérer en tete" d´abord : donc tu auras bien 6,2. (il passe dans le cas 2 )

Par contre, ce qu´il faut c´est tester d´abord m_pQueue, avant m_pTete. (autrement dit permuter les tests 2 et 3)
Ainsi, normalement, il devrait passer dans la condition 3 quand tu mets ton 6.
Et, normalement, tu devrais bien avoir 2,6 a la sortie et non 6,2.
ça veut dire que ta sous fonction qui insert à m_pqueue (donc l´appel de 3 ) a un petit bug.

Vérifie déja que quand tu inseres ton 6, tu passes bien dans cette condition (la 3) APRES PERMUTATION. (avec un printf si tu n´as pas de débuggueur)

m-2
m-2
Niveau 10
27 septembre 2006 à 18:18:52

si je permute les conditions 2 et 3, il arrivera le meme bug (mais inverser) lorsque je vais insérer respectivement 6 et 2 :

6 passera par la condition 1, qui l´insère dans une liste vide

2 passera par condition 3 (maintenant 2 avec la permutation) et s´insère à la queue donc je vais avoir 6,2

le probleme c´est que les conditions 2 et 3 sont toujours vrais lorsqu´on insère le deuxieme éléments de la liste, donc il va toujours s´inséré dans la premiere condition qu´il rencontre!

godrik
godrik
Niveau 30
27 septembre 2006 à 18:19:02

notes qu´au pire tu peux detecter le cas en regardant ptr=beggin && ptr=end
...

Fvirtman
Fvirtman
Niveau 10
27 septembre 2006 à 18:22:07

De toute façon, dans le cas ou t´as un seul élément, il faut trancher ! et c´est a toi de trancher !
Soit tu inseres avant, soit tu inseres apres, mais de toute façon, c´est ambigu !

m-2
m-2
Niveau 10
27 septembre 2006 à 18:33:00

c´est très ambigu... d´ou ma question : comment faire pour savoir si je dois insérer avant ou apres..!

godrik
godrik
Niveau 30
27 septembre 2006 à 18:39:26

En fait, c´est toi qui voit, c´est toi qui écris la lib...

Ici, tu cherches a mimer la STL alors regarde ce qu´elle fait.

Sous forums
  • Aide à l'achat Mac
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment