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 :

Arbre binaire de recherche - Suppression d'un nœud


Sujet :

C

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 90
    Par défaut Arbre binaire de recherche - Suppression d'un nœud
    Bonjour,

    J'ai besoin de créer une API spécifique pour des ABR. L'ensemble fournit les résultats escomptés à l'exception de la suppression d'un nœud.
    En effet, le nœud est supprimé et l'arbre réorganisé SAUF si le nœud demandé est le nœud racine, auquel cas je rentre dans une boucle infinie.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct btree
    {
        int key;
        struct btree *left;
        struct btree *right;
    } *btree;
    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
    static btree _btremove (btree tree, int key)
    {
        btree node = tree, *father = &tree;
        btree newnode, *newfather;
        while (node != NULL)
        {
            if (key == node->key)
                break;
            if (key < node->key)
            {
                father = &node->left;
                node = node->left;
            }
            else
            {
                father = &node->right;
                node = node->right;
            }
        }
        if (node != NULL)
        { 
            if (node->left == NULL)
            {
                if (node->right == NULL)
                {
                    *father = NULL;
                    free (node);
                    node = NULL;
                }
                else /* node->right != NULL */
                {
                    *father = node->right;
                    free (node);
                    node = NULL;
                }
            }
            else /* node->left != NULL */
            {
                if (node->right == NULL)
                {
                    *father = node->left;
                    free (node);
                    node = NULL;
                }
                else /* node->right != NULL */
                /* we search the smaller value in the right tree */
                {
                    newnode = node->right;
                    newfather = &node->right;
                    while (newnode != NULL)
                    { 
    /* Si le nœud demandé est la racine, boucle infinie ici ! */
                        if (newnode->left != NULL)
                        {
                            newfather = &newnode->left;
                            newnode = newnode->left; 
                        }
                    }
                    node->key = newnode->key;
                    *newfather = newnode->right;
                    free (newnode);
                    newnode = NULL;
                }
            }
        }
        return tree;
    }
    La boucle infinie est signalée par un commentaire.
    Je ne comprends pas pourquoi le nœud à cet endroit est une fuille.
    Pouvez-vous m'éclairer ?
    Pb d'algo ?

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    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 392
    Par défaut
    Peut-être devrais-tu le récupérer avant de faire la modification.
    Et aussi, séparer ta fonction un peu plus (notamment isoler les phases de recherche).

    Edit:
    Comme plan, je proposerais:

    Code C : 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
    /*Retourne un pointeur vers le pointeur vers le nœud qu'on cherche*/
    btree* FindPtrToNode(btree *ppRoot, int key)
    {
    	btree *ppCurrent = ppRoot;
    	if(ppCurrent==NULL)
    		return NULL;
    	while(*ppCurrent != NULL)
    	{
    		if((*ppCurrent)->key == key)
    			break;
    		else if((*ppCurrent)->key < key)
    			ppCurrent = &( (*ppCurrent)->left );
    		else
    			ppCurrent = &( (*ppCurrent)->right );
    	}
    	return ppCurrent;
    }
     
    /*Retourne un pointeur sur le pointeur du fils le plus à gauche*/
    btree* FindPtrLeftmost(btree* ppNode)
    {
    	btree* ppPrevious = ppNode;
    	if(ppNode==NULL)
    		return NULL;
    	while(*ppNode != NULL)
    	{
    		ppPrevious = ppNode;
    		ppNode = &( (*ppNode)->left );
    	}
    	return ppPrevious;
    }
     
    void Remove(btree *ppNode)
    {
    	/*Algorithme de suppression qui aura besoin de FindPtrLeftmost().*/
    }
     
    void FindAndRemove(btree *ppRoot, int key)
    {
    	btree* ppDelete = FindPtrToNode(ppRoot, key);
    	Remove(ppDelete);
    }
    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 Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Ce qui est étonnant, c'est justement la phase de recherche : tu cherches à atteindre une feuille : while (node != NULL)... donc nécessairement tu ne modifieras jamais la racine ni les noeuds dans les branches...

    EDIT : Oui avec un break tu sors de la boucle.... c'est vrai....
    My bad.
    C'est juste que je me refuse à faire des break ou continue donc je ne les cherche même pas.
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 90
    Par défaut
    Oui tout à fait d'autant que j'ai déjà une fonction récursive de recherche ... plus adaptée me semble-t'il que cette boucle itérative.

    @Metalman si le nœud est non null, c'est que justement ce n'est pas une feuille non ?

  5. #5
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    C'est corrigé... il y avait un break, donc oui tu sors bien de la boucle.
    As-tu essayé d'ajouter du debug pour voir où tu es dans l'arbre au moment où tu supprimes, les valeurs passées, etc...

    J'avais hésité à le poster plus tôt, mais tu es sûr que tu modifieras la racine de l'arbre avec cette fonction ?
    Elle ne retourne pas de pointeur, et ne "peut pas" modifier le paramètre fourni...
    Donc l'appelant ne pourra avoir qu'une épée-de-segfaultès au dessus de sa tête/en variable
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 90
    Par défaut
    Oui pour le debug. Pour un nœud autre que la racine, l'arbre est parcouru correctement et le nœud supprimé.
    Lorsque le nœud à supprimer est la racine, cette seconde boucle while boucle à l'infinie sur le nœud ... racine qui n'aurait donc pas de fils.

    Alors effectivement, je me demande si le problème ne vient pas de ce break, dans la première boucle while, inadapté dans ce cas particulier ??

    Je vais déjà éclaircir ce bout de code comme l'a intelligemment suggéré Medinoc !

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 90
    Par défaut
    Dans le code présenté ici, j'ai ajouté un else break dans la seconde boucle, afin de pallier le cas de l'absence de nœud gauche.

    La fonction n'était pas très jolie, je l'ai donc découpée et je les ai passées en mode récursif (préférence personnelle pour ce dernier point).

    Merci pour vos commentaires qui m'ont favorablement guidé. Je passe en Résolu.

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

Discussions similaires

  1. Suppression dans un arbre binaire de recherche
    Par allomona dans le forum Algorithmes et structures de données
    Réponses: 10
    Dernier message: 06/12/2014, 08h51
  2. Méthode de suppression pour Arbre Binaire de recherche
    Par TheRogerFederer dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 28/11/2014, 11h49
  3. Algorithme de suppression d'un élément dans un arbre binaire de recherche
    Par mohsenuss91 dans le forum Algorithmes et structures de données
    Réponses: 11
    Dernier message: 24/12/2011, 12h05
  4. Suppression dans un arbre binaire de recherche
    Par zeine77 dans le forum Langage
    Réponses: 1
    Dernier message: 11/05/2007, 20h40
  5. Réponses: 3
    Dernier message: 31/12/2005, 12h30

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