OVH Cloud OVH Cloud

arbres, listes chainées ...

19 réponses
Avatar
Gael
Bonjour,

j'espère que ma question n'est pas trop triviale: "je débute".

Je cherche un exemple d'algorithme pour manipuler un arbre (je ne sais
pas quel type de données utiliser).

Mon objectif est de recueillir des données externes, les manipuler
(opérations sur chaines de caractères, tri, ...) pour ensuite écrire un
fichier XML.

J'avais fait ce genre de choses jadis en C, mais sans pointeur, je ne
sais pas comment le réaliser.

Merci d'avance.

9 réponses

1 2
Avatar
Jerome
Gael wrote:

Je cherche un exemple d'algorithme pour manipuler un arbre (je ne
sais pas quel type de données utiliser).




en python tu as le choix
- structure récursive
- structure itérative avec un tableau
- arbre dom
- ...

je peux te filer des exmples pour tout ce que je cite si tu veux

Oui, je suis preneur !




class Node:
def __init__(self, cnt=''):
self.cnt = cnt
self.sons = []


class LinTree:

def __init__(self, root = 0):
self.nodes = []
self.root = root

def __repr__(self):
s = ''
to_deal = [self.root]
while to_deal:
n = self.nodes[to_deal[0]]
del to_deal[0]
s += str(n.cnt)

to_deal += n.sons
return s


t = LinTree()

a = Node('root')
b = Node('fils_gauche')
c = Node('fils_droit')

t.nodes.append(a)
t.nodes.append(b)
t.nodes.append(c)
a.sons = [1,2]

print t

C'est une version minimale d'une implémentation que j'utilise pour
stocker l'arbre dans une liste python. Les fils sont juste les indices
des éléments de la liste.



Avatar
Jerome
Gael wrote:

Je cherche un exemple d'algorithme pour manipuler un arbre (je ne
sais pas quel type de données utiliser).




en python tu as le choix
- structure récursive
- structure itérative avec un tableau
- arbre dom
- ...

je peux te filer des exmples pour tout ce que je cite si tu veux

Oui, je suis preneur !



import libxml2

doc = libxml2.newDoc('1.0')
a = doc.newDocNode(None, 'root', None)
b = doc.newDocNode(None, 'fils_gauche', None)
c = doc.newDocNode(None, 'fils_droit', None)

doc.setRootElement(a)
a.addChild(b)
a.addChild(c)

print doc.serialize(format=1)


La version que je te conseille... Autant travailler directement dans le
monde xml si c'est ce que tu souhaites faire après.



Avatar
nico

/logistique/item1/item2

je dois écrire:

<node "logistique">
<node "item1">
<node "item2/>
</node>
</node>

or en écrivant au fur et à mesure j'aurais déjà écrit:
<node "logistique/> en première ligne.

Et ben il suffit de regarder s'il y a quelquechose derriere avant de fermer le noeud.


Donc oui, il me semble avoir besoin d'un arbre.
Je pense que les listes sont tout à fait adaptées. Une liste peut contenir des listes qui peuvent contenir des listes qui...

Et en plus, on peut facilement trier une liste.

Pour que les listes soient nommées, j'utiliserait un dictionaire pour chaque entrée de la liste.
Liste = [SousListe1, SousListe2, SousListe3]
SousListex = {'Nom sous liste' : ListeDesElements}

Je suis aussi débutant en python alors, peut-être que ça marche pas. Mais c'est ce que j'essairais de faire.

Nicolas

Avatar
bruno modulix
Gael wrote:
En fait, je lis les infos suivantes :




Dans une arborescence de fichiers ?



Non, plutôt dans un fichier plat (peu importe en fait).


Si. L'arborescence de fichiers est déjà - comme son nom l'indique - une
arborescence !-)

(snip exemple)

A tu vraiment besoin d'un arbre pour ça ? Qu'est-ce qui t'empêche de
générer ton XML au fur et à mesure ? Je fais ça à longueur d'année
pour générer des menus ou des plans de sites en HTML, et c'est assez
trivial.



Je ne doute pas que ce soit trivial ... n'empêche que je sais pas le faire.


Si tu a déjà une structure arborescente, il suffit d'une fonction
récursive pour la parcourir... Example (quick&dirty):


import os, os.path
import sys

def tree2xml(root, level=0, indent=2, stream=sys.stdout):
space = " " * level * indent
for node in root.nodes():
if node.is_leaf():
print >> stream, "%s<node id='%s'/>" % (space, node.id)
else:
print >> stream, "%s<node id='%s'>" % (space, node.id)
tree2xml(node, level+1, indent, stream)
print >> stream, "%s</node>" % space

# L'interface supposée est

class AbstractNode(object):
def __init__(self, id):
self.id = id

def is_leaf(self):
"""Returns true if we don't have child nodes"""
return len(self.nodes()) == 0

def nodes(self):
""" Returns child nodes list """
raise NotImplemented


# Il suffit après ça de wrapper l'accès à l'arborescence
# dans une sous-classe de AbstractNode.
# exemple (simpliste) pour un système de fichiers:

class FSNode(AbstractNode):
def __init__(self, path):
self._path = os.path.abspath(path)
if not os.path.exists(self._path):
raise ValueError, "path %s does not exists" % self._path
super(FSNode, self).__init__(os.path.basename(path))
# don't compute it before we need it:
self._nodes = None

def nodes(self):
if self._nodes is None:
if os.path.isdir(self._path):
self._nodes = [self.__class__(
os.path.join(self._path,
fpath))
for fpath in os.listdir(self._path)]
else:
self._nodes = ()

return self._nodes

root = FSNode(os.getcwd())
tree2xml(root)


Je ne peux pas écrire au fur et à mesure, car je jeux trier chaque
arborescence et sous arborescence par ordre alphabétique,


Ok; donc tu a effectivement besoin d'une arborescence. Ton exemple
m'avait laissé penser qu'il s'agissait juste de parcourir une
arborescence existante, mais le problème est autre.

(snip)
Donc oui, il me semble avoir besoin d'un arbre.


Je confirme...

Je pense que ces deux liens peuvent t'être utiles:
* http://www.brpreiss.com/books/opus7/
* http://gnosis.cx/TPiP/

HTH
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"



Avatar
bruno modulix
nico wrote:

/logistique/item1/item2

je dois écrire:

<node "logistique">
<node "item1">
<node "item2/>
</node>
</node>

or en écrivant au fur et à mesure j'aurais déjà écrit:
<node "logistique/> en première ligne.

Et ben il suffit de regarder s'il y a quelquechose derriere avant de

fermer le noeud.


Ce qui implique, *pour chaque noeud*, de faire une passe complète sur le
(reste du) source. C'est effectivement une solution. A priori moins
rapide, a priori aussi moins gourmande en mémoire.

Donc oui, il me semble avoir besoin d'un arbre.


Je pense que les listes sont tout à fait adaptées. Une liste peut
contenir des listes qui peuvent contenir des listes qui...


Oui, c'est une des implémentations possible des arbres. Dans la
pratique, ce n'est pas forcément la plus "conviviale" pour le développeur.

Et en plus, on peut facilement trier une liste.
Pour que les listes soient nommées, j'utiliserait un dictionaire pour
chaque entrée de la liste.
Liste = [SousListe1, SousListe2, SousListe3]
SousListex = {'Nom sous liste' : ListeDesElements}


etc etc... Tu nous fais un aperçu de la structure de donnée avec 4 ou 5
niveaux d'imbrication ?-)

Je suis aussi débutant en python alors, peut-être que ça marche pas.
Mais c'est ce que j'essairais de faire.


Si, ça fonctionne, bien sûr, mais ça devient vite dur à gérer.

En fait, la solution objet est dans une certaine mesure similaire (un
objet Python est aussi basé sur des dictionnaires, celui de l'instance
et celui de sa classe), mais en plus lisible (enfin, AMHA).

class Node(object):
def __init__(self, cnt):
self._cnt = cnt # content
self._childrens = []

# ici toutes les methodes pour gérer l'arbo
# (ajout d'enfant, suppression d'enfants, parcours etc)


--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"


Avatar
Guillaume Bouchard
Do Re Mi chel La Si Do wrote:
J'aime bien le terme "référence". Ça me plait, ce mot.
Donc, à partir de dorénavant, sans tarder, ni plus attendre, je dirai : "Une
'variable' Python est un nom qui référence un objet".


D'un autre coté, moi j'en cherche encore des variables en python.

Quelle est la difference entre a et math.random ? Ce sont deux noms qui
referencent deux objects. Ou est la variable, ou est l'autre truc ?


@-salutations


i-salutations

--
Guillaume

Avatar
Do Re Mi chel La Si Do
Bonjour !


Comme tu dis, les deux noms référencent des objets.

D'ailleurs, rien ne t'empêche de faire :
a = math.random
sauf que math.random n'existe pas

Disons, alors, rien ne t'empêche de faire :
a = math.pi

Et rien ne t'empêche de faire l'inverse :
a3.1144
math.pi=a

Donc, inutile de chercher une différence, là où il n'y en a pas. C'est du
temps perdu, non productif.

Et, avec le temps (donc l'argent) gagné, tu pourrais payer à boire aux
participants de ce NG, et à moi en particulier.



@-salutations

Michel Claveau
Avatar
bruno modulix
Guillaume Bouchard wrote:
Do Re Mi chel La Si Do wrote:

J'aime bien le terme "référence". Ça me plait, ce mot.
Donc, à partir de dorénavant, sans tarder, ni plus attendre, je dirai
: "Une 'variable' Python est un nom qui référence un objet".



D'un autre coté, moi j'en cherche encore des variables en python.

Quelle est la difference entre a et math.random ? Ce sont deux noms qui
referencent deux objects. Ou est la variable, ou est l'autre truc ?


Effectivement, le terme "officiel" est "binding" (liaison), et le
concept est bien celui d'une liaison entre un nom et un objet. Il n'y a
pas de 'variables' en Python, du moins pas de le sens que ça a en C (où
une variable correspond à une adresse et un offset mémoire).

Le fait qu'en plus tout en Python soit objet (fonctions, classes et
modules inclus) contribue à nous éloigner des concepts du C :
math.random est un nom qui référence (a priori...) l'attribut 'random'
de l'objet référencé par le nom 'math' - quelques soient ces objets.


@-salutations



i-salutations

p-salutions !-)


('p' pour 'Python' ? 'p' pour 'pédant' ? je vous laisse le choix...!-)

--
bruno desthuilliers
ruby -e "print ''.split('@').collect{|p|
p.split('.').collect{|w| w.reverse}.join('.')}.join('@')"
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in ''.split('@')])"


Avatar
Laurent Pointal
Gael wrote:
Bonjour,

j'espère que ma question n'est pas trop triviale: "je débute".

Je cherche un exemple d'algorithme pour manipuler un arbre (je ne sais
pas quel type de données utiliser).

Mon objectif est de recueillir des données externes, les manipuler
(opérations sur chaines de caractères, tri, ...) pour ensuite écrire un
fichier XML.

J'avais fait ce genre de choses jadis en C, mais sans pointeur, je ne
sais pas comment le réaliser.

Merci d'avance.


<pub>
La lecture de la page suivante devrais éclairer certains points
(références, espaces de noms...):

http://wikipython.flibuste.net/moin.py/QuestionsGenerales

</pub>

A+

Laurent.

1 2