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++Builder Discussion :

Recursivité en listes chaînées, comment?


Sujet :

C++Builder

  1. #1
    bruce-willis
    Invité(e)
    Par défaut Recursivité en listes chaînées, comment?
    J'utilise C++ Builder depuis quelques mois, j'ai utilisé Delphi depuis que j'ai appris à programmer.
    Je sais créer une fonction de création de liste chaînée FIFO en Delphi:
    procedure createfile(var L:axe;elt:string);
    begin
    if L=nil then
    begin
    new(L);L^.value:=elt;
    L^.next:=nil;
    end
    else createfile(L^.next,elt);
    end;

    J'ai essayé la même chose en C++ Builder et ça ne se compile même pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void createfile(axe ** L,AnsiString elt){
    if (L==NULL){
    	L=(axe*) malloc(sizeof(axe));
    	L->value=elt;L->next=NULL;
    }
    else createfile(L->next,elt);
    }

  2. #2
    Membre expert
    Avatar de Sunchaser
    Homme Profil pro
    OPNI (Objet Programmant Non Identifié)
    Inscrit en
    Décembre 2004
    Messages
    2 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : OPNI (Objet Programmant Non Identifié)
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 059
    Points : 3 204
    Points
    3 204
    Par défaut
    Bonsoir,

    Ch'tite question ... dans le code en C++Builder, 'axe' est de quel type ?
    (c'est peut être idiot, mais je vois pas ...)

    @ +
    Aux persévérants aucune route n'est interdite.
    Celui qui ne sait pas se contenter de peu ne sera jamais content de rien.
    Current Status
    Avec 40% de pollinisateurs invertébrés menacés d'extinction selon les Nations Unies, l'homme risque fort de passer de la monoculture à la mono diète...
    Faîtes quelque chose de bien avec vos petits sous: Enfants du Mekong

  3. #3
    bruce-willis
    Invité(e)
    Par défaut
    axe est une structure (liste chaînée).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    struct axe{
          AnsiString value;
          struct axe * next;
    };
    Je voudrais savoir les erreurs de * ou de -> que j'ai omises dans cette fonction recursive.

  4. #4
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    bonjour
    simplement comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void __fastcall  TForm1::createfile(axe *L,AnsiString elt)
    {
    	if (L==NULL)
    	{
    	 L=new axe;
    	 L->value=elt;
    	 L->next=NULL;
    	}
    else createfile(L->next,elt);
    }
    cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  5. #5
    bruce-willis
    Invité(e)
    Par défaut
    Une question:

    DjmSoftware,tu as mis un seul *
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void __fastcall  TForm1::createfile(axe *L,AnsiString elt)
    Est-ce que ce n'est pas 2 * => axe **L?
    Car le contenu de la liste chaînée risque de rester inchangé!

    Ou je me trompe?

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    En effet :
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void __fastcall TForm1::createfile(axe **pL, AnsiString elt)
    {
    	if(*pL==NULL)
    	{
    		axe *L = new axe;
    		L->value=elt;
    		L->next=NULL;
    		*pL = L;
    	}
    	else 
    		createfile((*pL)->next,elt);
    }
    PS: Penser à renvoyer une erreur si pL est 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.

  7. #7
    bruce-willis
    Invité(e)
    Par défaut
    Bon je vais tester ce code et je donnerai des nouvelles après.

    Je n'ai pas BCB maintenant mais je crois bien que j'ai déja essayé ce code!

  8. #8
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    Je ne comprend pas trop ce code.
    S'il est récursif... on fait comment pour en sortir ?
    Personnellement, j'aurais utilisé une classe avec un constructeur sachant monter une liste liée de n éléments.

    Voici un exemple qui se sert de TComponent juste parce que c'est le propriétaire qui détruit les composants qu'il détient...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class jObject : public TComponent
    {
    public :
    int Code;
    jObject *Next;
        __fastcall jObject(TComponent *Owner, int nbObjects);
        __fastcall ~jObject();
    };
    Le constructeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    __fastcall jObject::jObject(TComponent *Owner, int nbObjects)
        : TComponent(Owner)
    {
    Code = nbObjects-1;
    Next = NULL;
    if(Code > 0) Next = new jObject(Owner, Code);
    }
    Usage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    jObject *List;
     
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    List = new jObject(this, 10);
    }
    Pour voir ce que ça donne, j'ai un TSpeedbutton et un TMemo

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
    {
    Memo1->Clear();
    jObject *Object = List;
    while(Object != NULL)
        {
        Memo1->Lines->Add(IntToStr(Object->Code));
        Object = Object->Next;
        }
    }
    A moins évidemment de n'avoir pas compris le problème...

    A plus !

  9. #9
    bruce-willis
    Invité(e)
    Par défaut
    Slt Henderson!

    L'utilisation de fonction recursive signifie rapidité.
    C'est comme créer un arbre binaire mais ici, on a un arbre unaire (liste chainée FIFO).

    Je crois que tu n'as pas compris le problème, il s'agit d'une structure pour stocker des "value" et mon prob est que ma fonction ne marche pas (prob de pointeur)
    ___________________
    Entre temps, ton code fait une erreur [Lieur Erreur] Unresolved external '__fastcall jObject::~jObject()' referenced from D:\...
    ___________________
    Pour Medinoc!
    Dans le code que tu as écris, où est-ce qu'on déclare L
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (L==NULL)//if (pL=NULL)
    Ca fait l'erreur suivante sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    else createfile((*pL)->next,elt);
    [C++ Erreur] Unit1.cpp(69): E2034 Impossible de convertir 'axe *' en 'axe * *'

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    En effet, il faut corriger en ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    else createfile(&((*pL)->next),elt);
    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.

  11. #11
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut !

    De temps en temps... j'ai le cerveau lent et aujourd'hui... ça craint !

    Je pense qu'un while serait plus rapide.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while(*pL != NULL) pL = &(*pL)->next;
    *pL = new axe;
    (*pL)->value = elt;
    (*pL)->next = NULL;
    Le plus rapide étant bien entendu d'avoir un pointeur sur le dernier entré.

    A plus !

  12. #12
    Membre expérimenté
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 218
    Points : 1 437
    Points
    1 437
    Par défaut
    (thanks)
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  13. #13
    Membre expérimenté
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 218
    Points : 1 437
    Points
    1 437
    Par défaut
    Je crois qu'il y a eu un prob dans le forum. Le serveur a posté mon message au mauvais forum.

    Désolé bruce-willis d'avoir parlé d'une autre discussion!!!
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  14. #14
    Membre expérimenté
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 218
    Points : 1 437
    Points
    1 437
    Par défaut Récursivité la meilleure
    --------------------------------------------------------------------------------

    Pour bruce-willis,

    je crois que ça marche maintenant là car j'ai testé le code avec la rectif de Médinoc, c'est OK

    Pour henderson, la récursivité est trop rapide par rapport à une itération, je n'ai mêm pas besoin de le prouver, tester ce code de bruce-willis.

    Voici comment on va appeler cette fonction:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    axe * list;
    list=NULL;
    createfile(&list,1);createfile(&list,1000);//etc.
    randriano.dvp.com
    Développeur. Product Owner [Agile]. Sites web, mobile apps, système d'information (SI).

  15. #15
    bruce-willis
    Invité(e)
    Par défaut
    OK rakoto15

    c'est résolu

    Merci à tous

  16. #16
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 374
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 374
    Points : 1 759
    Points
    1 759
    Par défaut
    Salut

    Dans ce contexte précis, je pense qu'un simple while est plus économique (temps d'éxucution + code machine) qu'un appel récursif !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void CreateFile(axe **pL, AnsiString elt)
    {
    while(*pL != NULL) pL = &(*pL)->next;
    *pL = new axe;
    (*pL)->value = elt;
    (*pL)->next = NULL;
    }
    Le while réduit le code de l'appel récursif à ce que cet appel est censé réaliser : la simple recherche d'une adresse nulle, d'adresse en adresse !

    Par ailleurs, je ne vois pas pourquoi il faudrait passer le paramètre elt pour cette recherche d'adresse nulle, puisqu'il y est totalement étranger !
    On s'oblige juste à devoir le faire à cause du mécanisme que l'on met soi-même en place !

    L'usage est le même donc je ne vois pas pourquoi on tire sur l'ambulance !

    A titre perso, j'aurais objétisé pour gérér le first_in et le last_in afin d'éviter de passer en revue l'ensemble des éléments juste pour trouver le dernier.

    Il semble qu'ici, la récursivité soit plus un sujet de TP qu'une optimisation. Donc c'est fait !

    A plus !

Discussions similaires

  1. Réponses: 4
    Dernier message: 21/11/2010, 15h54
  2. [Liste simplement chaînée] comment passer d'un élément à un autre ?
    Par beegees dans le forum Algorithmes et structures de données
    Réponses: 21
    Dernier message: 18/02/2008, 22h32
  3. Construction de liste chaînées
    Par fomblardo dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 15/03/2005, 21h19
  4. Insertion d'un noeud dans une liste chaînée
    Par habib106 dans le forum Assembleur
    Réponses: 8
    Dernier message: 07/04/2004, 22h34
  5. [MFC] list box : comment ça marche
    Par runn2 dans le forum MFC
    Réponses: 4
    Dernier message: 28/01/2004, 12h36

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