2016-03-26 6 views
2

J'ai une implémentation récursive d'une traversée d'arbre de pré-commande modifiée (nested set model) que je veux implémenter sans utiliser la récursivité.Traçage de l'arbre de pré-programmation modifié par pile

from collections import deque 

def mptt_recurse(tree, node, preorder=None): 

    if node not in tree: return 
    if preorder is None: preorder = deque() 

    for child in tree[node]: 
     preorder.append(child) 
     mptt_recurse(tree, child, preorder) 
     preorder.append(child) 

    return preorder 

La mise en œuvre récursive fonctionne comme prévu:

>>> tree = { 
    "root": ["food"], 
    "food": ["meat", "veg"], 
    "meat": ["pork", "lamb"], 
    "pork": ["bacon", "sausage"], 
    "lamb": ["cutlet"], 
    "soup": ["leak", "tomato"] 
} 
>>> mptt_recuser(tree, "root") 
deque(['food', 'meat', 'pork', 'bacon', 'bacon', 'sausage', 'sausage', 'pork', 'lamb', 'cutlet', 'cutlet', 'lamb', 'meat', 'veg', 'veg', 'food']) 

Chaque nœud apparaît deux fois avec des valeurs de gauche et de droite représentés par la position dans le deque.

def mptt_stack(tree, node): 

    if node not in tree: return 
    stack = deque(tree[node]) 
    preorder = deque() 

    while stack: 
     node = stack.pop() 
     preorder.append(node) 
     if node not in tree: 
      continue 
     for child in reversed(tree[node]): 
      stack.append(child) 

    return preorder 

Avec mon implémentation basée empilée je n'ai pu comprendre comment obtenir le pré-commande (pas le pré-commande modifiée avec les deux étiquettes gauche et à droite pour chaque nœud).

>>> mptt_stack(tree, "root") 
deque(['food', 'meat', 'pork', 'bacon', 'sausage', 'lamb', 'cutlet', 'veg']) 

Tout pointeur sur une implémentation non récursive serait génial.

Répondre

1

Cela donnera les mêmes résultats que mptt_recurse. Il conserve une information supplémentaire sur la pile, ce qui indique si elle est entrant ou sortant du nœud:

def mptt_stack(tree, node): 
    if node not in tree: return 
    preorder = deque() 

    stack = [] 
    for child in reversed(tree[node]): 
     stack.append([child, True]) 

    while stack: 
     (node, first) = stack.pop() 
     preorder.append(node) 
     if first: 
      stack.append([node, False]) 
      if node in tree: 
       for child in reversed(tree[node]): 
        stack.append([child, True]) 

    return preorder 

Si vous souhaitez inclure le nœud initial dans le résultat, vous pouvez remplacer la boucle initialisant stack avec:

stack = [[node, True]]