2011-02-13 12 views
5

Suponiendo que haya una lista de objetos que tienen los siguientes campos¿Cuál es la forma más eficiente de atravesar un árbol en Python?

padre

valor

y esto define una estructura de árbol, similar a un árbol de directorios.

Quiero atravesar la lista de forma anticipada. ¿Cuál es la forma más eficiente?

Normalmente, en otros idiomas (más imperativos) iteraría los valores, buscando los que no tienen padres, luego, para cada uno, iterando de nuevo para cada objeto cuyo padre es el que estoy viendo actualmente, etc. pero, ¿hay una forma más inteligente de hacer esto en Python?

Respuesta

7

Me gustaría en primer lugar crear una estructura de datos más adecuada - capturar el enlace de un padre a sus hijos:

children = {} 
for obj in tree: 
    children.setdefault(obj.parent, []).append(obj) 

def preorder(root, children): 
    yield root.value 
    for child in children.get(root, []): 
     for value in preorder(child, children): 
      yield value 

for root in children[None]: 
    for value in preorder(root, children): 
     print value 

También es posible usar collections.defaultdict aquí.

+4

Creo que podría ser mejor sin una carcasa especial 'Obj.parent no es None' en el cruce. Es menos código, más rápido y también puede manejar un bosque en lugar de un árbol ('children [None]' es la lista de todas las raíces de árbol). – 6502

+0

¡Excelente! Yo añadiría que usted podría cambiar: \t \t def preorden (raíz, los niños, profundidad): \t \t rendimiento [root.value, profundidad] \t \t para el niño en children.get (raíz, []) : \t \t para el valor en preorden (niño, niños, profundidad + 1): \t \t valor de rendimiento \t \t y de esa manera se podía ver no sólo el resultado preorden sino también cómo ev profunda ery nodo es. Tenga en cuenta que la primera llamada debe ser preordenar (raíz, hijos, 0) ¡Muchas gracias! ** Editar **: Urgh. el código parece muy complicado al responder. – Bruno

Cuestiones relacionadas