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

Algorithmes et structures de données Discussion :

Regex et arbres binaires


Sujet :

Algorithmes et structures de données

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2017
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mars 2017
    Messages : 93
    Points : 60
    Points
    60
    Par défaut Regex et arbres binaires
    Bonjour à tous,

    Je ne sais pas si je poste dans la bonne catégorie de forum (car je n'ai pas trouvé mieux) mais voici mon problème :

    Je suis en train de faire un exercice à propos des arbres binaires. L'idée est d'après une classe Node (qui représente un noeud de l'arbre), écrire une fonction "serializable(node)" qui transforme cet arbre en chaîne de caractères.
    J'ai déjà codé cette fonction et voici la manière dont j'ai formaté cette chaine :

    Code ruby : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    root(left(left.left($,$),$),right($,$))
     
    ou encore
     
    1(7($,$),3($,3($,$)))

    avec root(left,right) qui représente un noeud ("root", "left" et "right" peuvent être n'importe quelle chaine de caractères) et "$" l'absence de noeud fils.

    Maintenant il m'est demandé d'écrire la fonction "deserialize(str)" qui effectue l'opération inverse.
    Il me faut donc un moyen de parser la chaine et d'extraire les composantes (valeur du noeud, gauche et droite) du noeud récursivement.

    Je code en Ruby donc je peux utiliser facilement la fonction "String#split" qui prends en argument une expression régulière.
    J'aimerais donc avoir :

    Code ruby : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    root(left(left.left($,$),$),right($,$))
    left(left.left($,$),$)    right($,$)
    left.left($,$)   $       $    $
    $    $
     
    ou encore
     
    1(7($,$),3($,3($,$)))
    7($,$)    3($,3($,$)) 
    $  $        $    3($,$)

    et ainsi reconstruire l'arbre binaire.
    Ma question : à quoi doit ressembler cette expression régulière (parce que /\((.+),(.+)\)/ ne marche pas)

    N'hésitez pas à me poser des question si ce n'est pas assez clair. Merci d'avance

  2. #2
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 271
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 271
    Points : 13 536
    Points
    13 536
    Par défaut
    Bonjour

    • Left() OK
      Right() OK
      Root() Admettons. (quoique inutile et/ou inhomogène)
      Left.Left() ? Késako ? ( Qu'est-ce ? )
      .
    • De plus, 3 ne peut pas être le fils de 3 sinon, il y a un cycle et ce n'est plus un arbre.
      .
    • Je code en Ruby donc je peux utiliser facilement la fonction "String#split" qui prends en argument une expression régulière.
      Oui mais ton expression régulière symbolise le séparateur .
      Ruby ne va pas parser ta chaîne.
      Tu es bon pour une récurrence. ou une récursivité.
      Code ruby : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      "1(7($,$),3($,3($,$)))".split(/[(,)]/)
      # => donne ["1", "7", "$", "$", "", "3", "$", "3", "$", "$"]
      .
    • Si tu tiens aux regex, une autre idée :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      $ grep --color '[^,()]\+([^,()]*,[^()]*)' <<<"root(left(left.left($,$),$),right($,$))"
      root(left(left.left($,$),$),right($,$))
      $ grep --color '[^,()]\+([^,()]*,[^()]*)' <<<"1(7($,$),3($,3($,$)))"
      1(7($,$),3($,3($,$)))

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2017
    Messages
    93
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mars 2017
    Messages : 93
    Points : 60
    Points
    60
    Par défaut
    Bonjour @Flodelarab,

    Merci pour votre réponse. Je m'explique plus clairement :

    La représentation de ces arbres sont :

    Nom : Capture d’écran de 2019-03-22 10-31-19.png
Affichages : 406
Taille : 11,4 Ko
    Code ruby : Sélectionner tout - Visualiser dans une fenêtre à part
    0(-1($,$),9(3($,$),$))
    Nom : Capture d’écran de 2019-03-22 10-38-38.png
Affichages : 396
Taille : 18,2 Ko
    Code ruby : Sélectionner tout - Visualiser dans une fenêtre à part
    r(l($,ll($,$)),rr($,rrr($,$)))
    Mais ça peut être n'importe quelle chaine (ou nombre, sauf le caractère représentant l'absence de noeud $)

    C'est vrai que la solution ""1(7($,$),3($,3($,$)))".split(/[(,)]/)" peut marcher, il me suffira de parcourir cette liste recursivement en créant l'arbre.

    Bonne soirée

  4. #4
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 897
    Points : 6 661
    Points
    6 661
    Par défaut
    Tu peux utiliser une pattern récursive qui sera alors capable tout d'abord d'extraire la valeur du nœud, puis de différencier la partie gauche de la partie droite du nœud quelque soit la profondeur (\g<0> représente la pattern elle-même et permet donc la récursion):
    Code ruby : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    irb(main):001:0> "0(-1($,$),9(3($,$),$))".match(/(?<val>[^(),]+)\((?<left>\$|\g<0>),(?<right>\$|\g<0>)\)/)
    => #<MatchData "0(-1($,$),9(3($,$),$))" val:"3" left:"3($,$)" right:"9(3($,$),$)">

    ensuite il suffit d'appliquer la même pattern sur les parties gauche et droite obtenues (jusqu'à aboutir à $).

    Néanmoins, j'attire ton attention sur le fait que la pattern devra parser les mêmes morceaux de chaîne x fois (x dépendant de la profondeur de l'arbre).

    D'un point de vue algorithmique, il est bien meilleur de tokenizer la chaîne:
    Code ruby : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    irb(main):005:0> "0(-1($,$),9(3($,$),$))".scan(/[^(),]+|./)
    => ["0", "(", "-1", "(", "$", ",", "$", ")", ",", "9", "(", "3", "(", "$", ",", "$", ")", ",", "$", ")", ")"]

    puis de tester les tokens un par un pour savoir quoi faire.

    Maintenant en pratique, je ne peux pas te dire lequel sera le plus performant, ni à partir de quel niveau de récursion Nokogiri (le moteur de regex de Ruby) te lâchera.

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

Discussions similaires

  1. Afficher un arbre binaire avec sa structure
    Par PhoneKilleR dans le forum C
    Réponses: 7
    Dernier message: 23/04/2008, 23h24
  2. suppression d'un arbre binaire
    Par NomUtilisateurDejaPris dans le forum C
    Réponses: 11
    Dernier message: 16/02/2004, 10h05
  3. [Arbre binaire de Recherche]
    Par Giovanny Temgoua dans le forum Algorithmes et structures de données
    Réponses: 11
    Dernier message: 06/02/2004, 11h45
  4. Arbre binaire
    Par Heaven dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 02/02/2004, 19h01
  5. [LG]probleme de creation arbre binaire
    Par jsaviola dans le forum Langage
    Réponses: 2
    Dernier message: 06/01/2004, 20h57

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