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 :

Question sur les listes chainées.


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut Question sur les listes chainées.
    Bonjour

    J'ai dans un livre un exemple de listes chainées, dont je reproduis la classe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class Node{
    public:
    	int data;
    	Node *next;
            Node(int, Node*);
           //déclarations de fonction..
    };

    J'ai voulu optimisé les fonctions push et pull.
    La fonction push ajoute un objet à la suite des autres.

    J'ai transformé:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Node::push(Node** mapile,int valeur){
      Node* element=new Node(valeur,*mapile);
        *mapile=element; 
    }
    en:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void Node::push(Node* &mapile,int valeur){
      mapile=new Node(valeur,mapile);
     }
    >>La seule grosse différence est que dans le deuxième cas, je fait passer un pointeur sur une référence. Plus exactement, je fais passer la référence du pointeur sur mapile.
    Mais j'ai quand même du mal à comprendre la différence entre Node* mapile et Node* &mapile.



    La fonction pull est censée rajouter un objet en début de liste.

    j'ai aussi transformé ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void Node::pull(Node *ppile,int val){
     
     	 do{ppile=ppile->next;}while(ppile->next);
    	ppile->data=val;
    	ppile->next=new Node(0,0);	 
    }
    en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Node::pull(Node *ppile,int val){
    	  do{ppile=ppile->next;}while(ppile->next->next);
         ppile->next=new Node(val,ppile->next);	 
    }
    En effet, je préfère ce code au premier. Dans les deux cas, on crée en effet qu'un seul nouvel objet. Mais ce que cache le premier, c'est que le pointeur qui est en bout de liste, qui vaut 0, existe deja. Donc quand on fait: new Node(0,0), on crée une nouvelle fin de liste, alors qu'elle existe déjà. Dans le deuxième cas, on la conserve.
    On reconnecte simplement la fin de liste au nouvel objet.

    que pensez vous de mes modifs?
    Merci

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Pour la première question, je n'ai vu aucun pointeur sur référence dans ton code: Seulement une référence sur pointeur.

    Pour la seconde, j'ai deux remarques:
    Premièrement, je supporte totalement ta modif, car je suis contre les "objets de fin" pour les listes chaînées.
    Malheureusement, et j'en viens à mon second point, ce code ne prend pas en compte le cas où la liste est vide avant ajout. De plus, tu sautes le premier élément. C'est pourquoi je tends à faire mes fonctions ainsi à la place:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /*static*/ void Node::pull(Node **ppPremier, int val)
    {
    	assert(ppPremier != NULL);
     
    	Node **ppCourant = ppPremier;
    	while( (*ppCourant ) != NULL )
    		ppCourant  = &( (*ppCourant)->next ); //Pointe sur le pointeur suivant
    	//Maintenant, ppCourant pointe sur le pointeur nul à la fin de la liste
     
    	*ppCourant = new Node(val, NULL);
    }
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Merci pour la rép
    Pour la première question, je n'ai vu aucun pointeur sur référence dans ton code: Seulement une référence sur pointeur.
    Je suis ok!

    Premièrement, je supporte totalement ta modif,
    Ca fait plaisir.

    Malheureusement, et j'en viens à mon second point, ce code ne prend pas en compte le cas où la liste est vide avant ajout
    ok mais c'est une gestion d'exception. Ce n'est pas le corps de la fonction.

    De plus, tu sautes le premier élément. C'est pourquoi je tends à faire mes fonctions ainsi à la place:
    Je vais étudier ton code, mais à première vue, tu utilises des pointeurs sur pointeurs. Je veux éviter à tous prix des pointeurs sur pointeurs. J'ai trop de mal a comprendre leurs fonctionnements.
    C'est pour cela que j'avais mis une référence.


    De plus, tu sautes le premier élément.
    je vois ce que tu veux dire. Il faut utiliser deux fois la fonction push avant d'utiliser la fonction pull. C'était trop simple pour être vrai.

  4. #4
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Deux autres remarques:
    D'après ce Bjarne Sostrup sur son site, il vaut mieux utilisé le pointeur 0 que le pointeur NULL.

    De plus, je pense qu'il vaut mieux faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *ppCourant=new Node(val,*ppCourant);
    que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *ppCourant=new Node(val,0);
    , car sinon, on ne raccroches pas au pointeur 0.

    (Moi, je tiens à ce qu'il y ait un 0 à la fin de la liste).

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    D'après ce Bjarne Sostrup sur son site, il vaut mieux utilisé le pointeur 0 que le pointeur NULL.
    En fait, avec le prochain standard, le mieux sera d'utiliser nullptr. De toute façon, dans l'état actuel des choses, on a #define NULL 0 en C++, donc ça ne change pas grand-chose.
    De plus, je pense qu'il vaut mieux faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *ppCourant=new Node(val,*ppCourant);
    que

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *ppCourant=new Node(val,0);
    , car sinon, on ne raccroches pas au pointeur 0.
    Pour insérer à la fin, les deux sont rigoureusement équivalents. Par contre, le premier code est idéal pour insérer n'importe ou, ce qui fait qu'il est mieux, en effet

    Pour l'emploi des pointeurs de pointeurs, il n'y a pas trop le choix malheureusement. Je ne pense pas qu'on puisse facilement employer une référence dans la boucle, vu que les références ne peuvent pas être changées.

    Le principe est montré ici: On pointe directement sur le pointeur qu'on modifiera lors de l'insertion, et ce code marche aussi bien pour le premier élément que pour tous les suivants.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Je ne pense pas qu'on puisse facilement employer une référence dans la boucle, vu que les références ne peuvent pas être changées.
    C'est pour cette raison qu'on ne pourra jamais avoir qqch comme cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
       int a=3;
       int b=4; int *m=&b;
       &a=&b;
       &a=m;
    une référence ne peut pas être une lvalue, vue qu'elle est constant.

    De la même manière qu'on ne peut pas avoir:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int const pp=3;
      pp=4;
    Pourtant une fonction, qui renvoie une référence, peut être une lvalue, mais ce n'est pas la même chose.

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

Discussions similaires

  1. Question sur les listes doublement chainées.
    Par entropie67 dans le forum C
    Réponses: 2
    Dernier message: 09/02/2015, 15h12
  2. Question sur les listes d'affichage
    Par brouss dans le forum OpenGL
    Réponses: 3
    Dernier message: 08/03/2007, 12h56
  3. question sur les listes/set/vector
    Par deubelte dans le forum SL & STL
    Réponses: 11
    Dernier message: 04/01/2007, 20h41
  4. question sur les listes/set/vector
    Par deubelte dans le forum SL & STL
    Réponses: 16
    Dernier message: 28/12/2006, 20h17
  5. des questions sur les listes chainées
    Par hunter99 dans le forum C
    Réponses: 13
    Dernier message: 05/12/2006, 22h51

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