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

Python Discussion :

[Résolu] Parcours d'un arbre binaire et enregistrement des chemins pour arriver aux buts


Sujet :

Python

  1. #1
    Membre du Club
    Profil pro
    ceo
    Inscrit en
    Août 2005
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ceo

    Informations forums :
    Inscription : Août 2005
    Messages : 62
    Points : 48
    Points
    48
    Par défaut [Résolu] Parcours d'un arbre binaire et enregistrement des chemins pour arriver aux buts
    Bonjour,

    j'ai codé le code qui suit pour faire une recherche dans un arbre bianire qui n'est pas triée, mais j'ai été obligé d'utiliser une variable globale extérieure à la fonction pour enregistrer les résultats des chemins qui mènent à la valeur de feuille recherchée (il peut y avoir plusieurs fois la valeur recherchée). Voyez-vous un moyen de faire pour avoir ce résultat retournée par la fonction (et None s'il n'y en pas).

    Voici ce que j'ai fait :

    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
    # -*- coding: utf-8 -*-
     
    arbre = ['+', ['+', ['*', 4, ['*', 4, 2]], 2], ['*', ['*', 4, 2], 2]]# 
     
    def arbre_gauche(arbre) :
        return arbre[1]
     
    def arbre_droit(arbre) :
        return arbre[2]
     
    def est_vide(arbre) :
        if arbre == [] : #???
            return True
        else :
            return False
     
    #print arbre_gauche(arbre)
     
     
    Res = []
     
    #retourne le chemin pour mener à la feuille si elle a été trouvée,False sinon
    def recherche(feuille, arbre, chemin = []) :
        global Res
        if est_vide(arbre) :
            return 
        if isinstance(arbre_gauche(arbre), list) :
            recherche(feuille, arbre_gauche(arbre), chemin + [1])
        if isinstance(arbre_droit(arbre), list) :
            recherche(feuille, arbre_droit(arbre), chemin + [2])  
        if arbre_gauche(arbre) == feuille :
            chemin += [1]
            Res += [chemin]
            return 
        if arbre_droit(arbre) == feuille :
            chemin += [2]
            Res += [chemin]
            return
     
     
    recherche(12, arbre)
    print Res
    Merci d'avance pour vos réponses!

  2. #2
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Salut,

    Ce n'est pas une question de global, ton code ne peut pas aboutir.

    Les deux conditions qui peuvent modifier Res sont:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        if arbre_gauche(arbre) == feuille :
            ... 
        if arbre_droit(arbre) == feuille :
    feuille vaut 12 et ne varie jamais et, ni arbre_gauche, ni arbre_droit ne peuvent retourner 12.

    Conclusion, Res reste []

  3. #3
    Membre du Club
    Profil pro
    ceo
    Inscrit en
    Août 2005
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ceo

    Informations forums :
    Inscription : Août 2005
    Messages : 62
    Points : 48
    Points
    48
    Par défaut
    Salut et merci de ta réponse. Mon code marche, là en effet res vaudra [] mais si j'exécute recherche(2, arbre) j'aurais les bons résultats dans res. Mon problème est de coder ceci plus joliment, et de façon à pouvoir utiliser if recherche(2, arbre) == None : plutôt que de faire recherche(2, arbre) et tester si Res == None.
    A la limite si ce n'est pas possible en renvoyant toutes les solutions, en renvoyer une seule m'irait, mais je ne sais pas comment sortir de la fonction et arreter les autres appels récursifs si une solution a été trouvé (sans utiliser la fonction exit() ).

  4. #4
    Expert éminent

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 300
    Points : 6 780
    Points
    6 780
    Par défaut
    Tu peux passer la liste en argument, c'est pareil.

    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
     
    # -*- coding: utf-8 -*-
     
    arbre = ['+', ['+', ['*', 4, ['*', 4, 2]], 2], ['*', ['*', 4, 2], 2]]
     
    def arbre_gauche(arbre) :
        print 'gauche:', arbre[1]
        return arbre[1]
     
    def arbre_droit(arbre) :
        print 'droit:', arbre[2]
        return arbre[2]
     
    def est_vide(arbre) :
        if arbre == [] : # if not arbre:
            return True
        else :
            return False
     
    #retourne le chemin pour mener à la feuille si elle a été trouvée,False sinon
    def recherche(feuille, arbre, Res, chemin = []) :
     
        if est_vide(arbre) :
            return
        if isinstance(arbre_gauche(arbre), list) :
            recherche(feuille, arbre_gauche(arbre), Res, chemin + [1])
        if isinstance(arbre_droit(arbre), list) :
            recherche(feuille, arbre_droit(arbre), Res, chemin + [2])  
        if arbre_gauche(arbre) == feuille :
            chemin += [1]
            Res += [chemin]
            return Res
        if arbre_droit(arbre) == feuille :
            chemin += [2]
            Res += [chemin]
            return Res
        return Res
     
    ch = recherche(2, arbre, [])
    print ch
    J'ai testé avec feuille = 2 les deux versions, j'ai le même résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    [[1, 1, 2, 2], [1, 2], [2, 1, 2], [2, 2]]

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par simnitch Voir le message
    Salut et merci de ta réponse. Mon code marche, là en effet res vaudra [] mais si j'exécute recherche(2, arbre) j'aurais les bons résultats dans res. Mon problème est de coder ceci plus joliment, et de façon à pouvoir utiliser if recherche(2, arbre) == None : plutôt que de faire recherche(2, arbre) et tester si Res == None.
    C'est une fonction récursive.
    Plutôt que de trimbaler "chemin" en variable locale essayez de vous en débarrasser.
    L'idée étant de remplacer des formes comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        if isinstance(arbre_gauche(arbre), list) :
            recherche(feuille, arbre_gauche(arbre), chemin + [1])
    par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        if isinstance(arbre_gauche(arbre), list) :
            return [1] + recherche(feuille, arbre_gauche(arbre))
    i.e. on remplace la variable locale par le résultat d'un calcul "local".

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Membre expérimenté Avatar de davcha
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 258
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 258
    Points : 1 539
    Points
    1 539
    Par défaut
    Dans le pire des cas, tu peux toujours faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def foo(params):
      buffer = []
      def bar(params):
         ...
         buffer = ....
         ...
      bar(params)
      return buffer

  7. #7
    Membre du Club
    Profil pro
    ceo
    Inscrit en
    Août 2005
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ceo

    Informations forums :
    Inscription : Août 2005
    Messages : 62
    Points : 48
    Points
    48
    Par défaut
    Merci bien pour ta réponse wiztricks!
    J'ai donc testé un truc comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def recherche(feuille, arbre) :
        if est_vide(arbre) :
            return False
        if isinstance(arbre_gauche(arbre), list) :
            if recherche(feuille, arbre_gauche(arbre)) == False : return False
            return [1] + recherche(feuille, arbre_gauche(arbre))
        if isinstance(arbre_droit(arbre), list) :
            if recherche(feuille, arbre_droit(arbre)) == False : return False
            return [2] + recherche(feuille, arbre_droit(arbre))
        if arbre_gauche(arbre) == feuille :
            return [1]
        if arbre_droit(arbre) == feuille :
            return [2]
        return False
    Mais j'ai deux problèmes, déjà je suis obligé (y'a sûrement une manière plus élégante de faire non?) de tester la valeur que retournera l'appel suivant pour ne pas avoir à concatener une liste et False. (Sinon il faudrait que je retourne [False] mais alors la fonction retournerait quand même une liste au lieu de False si elle n'a rien trouvée.) Autre gros problème, si la fonction arrive a un sous arbre dont les deux feuilles ne sont pas les feuilles recherchées, alors la fonction renvoie False et coupe les autres récursions, et je ne vois pas comment l'éviter.

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Ah oui c'est beurk...
    On pourrait écrire un truc comme çà:

    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
    LEFT = 1
    RIGHT = 2
     
    def recherche(feuille, arbre) :
     
        if len(arbre):
            for side in (LEFT, RIGHT):
                child = arbre[side]
                if isinstance(child, list):
                    found = recherche(feuille, child)
                    if found: 
                        return [side] + found
                if child == feuille:
                    return [side]
        return []
     
    print ('found', recherche(2, arbre))
    print ('*found*', recherche(12, arbre))
    Après le jeu serait de remplacer les "return" par "yield" pour récupérer tous les chemins.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Membre actif Avatar de Kurodiam
    Inscrit en
    Décembre 2013
    Messages
    208
    Détails du profil
    Informations forums :
    Inscription : Décembre 2013
    Messages : 208
    Points : 215
    Points
    215
    Par défaut
    @simnitch , vous avez utilisé trop de if , il serait de voir une suite de if et d'elif , et à la fin un else ( le return False se répète trop de fois , on dirait une condition générale , et il faudrait trier les conditions par ordre ) .C'est pour cette raison , qu'il y'a certaines conditions qui ne sont pas traitées par votre fonction .
    Pourquoi voulez-vous créer des listes de feuilles ? Le plus souvent , c'est plutôt le langage lisp qui aborde ce genre de soucis ...
    _""""Cats have a big heart ^^ unlike some bad people (whose will never change in their brain) """

  10. #10
    Membre du Club
    Profil pro
    ceo
    Inscrit en
    Août 2005
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : ceo

    Informations forums :
    Inscription : Août 2005
    Messages : 62
    Points : 48
    Points
    48
    Par défaut
    wiztricks : merci beaucoup, c'est beaucoup plus élégant comme ça.

    Kurodiam : c'est sûr qu'en lisp ce serait plus facile mais en lisp je sais faire, là j'essaie d'apprendre le python

    Merci pour vos réponses

  11. #11
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Juste pour le fun...
    Avec des "yield", on peut récupérer les chemins et c'est une petite variation du code précédent:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def search(leaf, tree):
        if not len(tree):
            return []
        for side in (LEFT, RIGHT):
            child = tree[side]
            if isinstance(child, list):
                for e in search(leaf, child):
                    yield [side] + e
            if child == leaf:
                yield [side]
     
    print ('***', list(search(2, arbre)))
    print ('***',list(search(12, arbre)))
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Réponses: 15
    Dernier message: 27/02/2014, 12h22
  2. Arbre binaire parcours iteratif
    Par line86 dans le forum C
    Réponses: 8
    Dernier message: 26/09/2007, 00h58
  3. Enregistrer des callback pour LUA
    Par aiolia_aiolos dans le forum Développement 2D, 3D et Jeux
    Réponses: 1
    Dernier message: 24/07/2007, 11h06
  4. Comment enregistrer des graphiques pour le web?
    Par pepe2006 dans le forum Access
    Réponses: 1
    Dernier message: 11/10/2005, 20h08

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