Ich versuche, eine Iterator-Klasse für nicht notwendigerweise binäre Bäume in Python zu implementieren. Nachdem der Iterator mit dem Wurzelknoten eines Baums konstruiert wurde, kann seine next()
-Funktion wiederholt aufgerufen werden, um den Baum in der Tiefe - erste Ordnung (z. B. this order) zu durchlaufen, wobei schließlich None
zurückgegeben wird, wenn keine Knoten mehr übrig sind.Implementieren eines Depth-First-Tree-Iterators in Python
Hier ist die grundlegende Node
Klasse für einen Baum:
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
Wie Sie oben sehen können, ich führte eine visited
Eigenschaft auf den Knoten für meinen ersten Ansatz, da ich nicht einen Weg, um es zu sehen war . Mit diesen Extramaß Zustand sieht die Iterator
Klasse wie folgt:
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()
Das alles ist schön und gut, aber ich mag für die visited
Eigenschaft von der Notwendigkeit zu befreien, ohne zu Rekursion zurückgreifen oder anderen Veränderungen in die Node
Klasse.
Der gesamte Zustand, den ich brauche, sollte im Iterator erledigt werden, aber ich weiß nicht, wie das gemacht werden kann. Eine besuchte Liste für den gesamten Baum zu halten ist nicht skalierbar und kommt nicht in Frage, also muss es einen cleveren Weg geben, den Stapel zu benutzen.
Was mich besonders verwirrt ist das - seit die next()
Funktion natürlich zurückkehrt, wie kann ich mich erinnern, wo ich gewesen bin, ohne irgendetwas zu markieren oder überschüssigen Speicher zu verwenden? Intuitiv denke ich daran, über Kinder zu schleifen, aber diese Logik ist gebrochen/vergessen, wenn die next()
Funktion zurückkehrt!
UPDATE - Hier ist ein kleiner 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
Das Führen einer besuchten * Liste * ist möglicherweise nicht skalierbar, aber was ist mit einem besuchten Satz, z. basierend auf Node-Objekt-ID? – michaelb
Das könnte aber immer noch jedes Etikett enthalten. Ich möchte, dass der Iterator immer nur eine Teilmenge des Baums behält. – nicole
Was ist die erwartete Ausgabe des "kleinen Tests"? –