Sto cercando di implementare una classe iteratore per alberi non necessariamente binari in Python. Dopo che l'iteratore è stato creato con il nodo radice di un albero, la sua funzione next()
può essere richiamata ripetutamente per attraversare l'albero in ordine di profondità (ad esempio, this order), restituendo infine None
quando non sono rimasti nodi.Implementazione di un iteratore di albero depth-first in Python
Ecco la Node
classe di base per un albero:
class Node(object):
def __init__(self, title, children=None):
self.title = title
self.children = children or []
self.visited = False
def __str__(self):
return self.title
Come potete vedere sopra, ho introdotto una proprietà visited
ai nodi per il mio primo approccio, dal momento che non ho visto un modo intorno ad esso . Con questo ulteriore misura di Stato, la classe Iterator
si presenta così:
class Iterator(object):
def __init__(self, root):
self.stack = []
self.current = root
def next(self):
if self.current is None:
return None
self.stack.append(self.current)
self.current.visited = True
# Root case
if len(self.stack) == 1:
return self.current
while self.stack:
self.current = self.stack[-1]
for child in self.current.children:
if not child.visited:
self.current = child
return child
self.stack.pop()
Questo è tutto bene, ma voglio sbarazzarsi della necessità per la proprietà visited
, senza ricorrere a ricorsione o altre alterazioni alla classe Node
.
Tutto lo stato di cui ho bisogno dovrebbe essere curato nell'iteratore, ma non riesco a capire come si possa fare. Mantenere una lista visitata per l'intero albero non è scalabile e fuori questione, quindi ci deve essere un modo intelligente per usare lo stack.
Ciò che soprattutto mi confonde è questo - poiché la funzione-, ovviamente, restituisce, come posso ricordare dove sono stato senza contrassegnare qualcosa o utilizzare la memoria in eccesso? Intuitivamente, penso al looping sui bambini, ma quella logica è rotta/dimenticata quando la funzione restituisce!
AGGIORNAMENTO - Ecco un piccolo test:
tree = Node(
'A', [
Node('B', [
Node('C', [
Node('D')
]),
Node('E'),
]),
Node('F'),
Node('G'),
])
iter = Iterator(tree)
out = object()
while out:
out = iter.next()
print out
Mantenere una * lista * visitata potrebbe essere non scalabile, ma per quanto riguarda un insieme visitato, ad es. in base all'ID oggetto Nodo? – michaelb
Questo potrebbe ancora potenzialmente contenere ogni etichetta, però. Voglio che l'iteratore mantenga solo un sottoinsieme dell'albero alla volta. – nicole
Qual è l'uscita prevista del "test di piccole dimensioni"? –