Zamiast wywoływać self.left/right.
in
_order_list()
, dzwonisz self.left/right.
pre
_order_list()
.
Aby osiągnąć to, co chcesz zrobić funkcję generator mogłoby być lepsze (mniej pamięci czasochłonne i bardziej pythonic) niż gromadzenie wartości w liście:
class Tree(object):
...
def in_order(self):
if self.left is not None:
for value in self.left.in_order():
yield value
yield self.value # <-- yielding the value of the node, not the node itself
if self.right is not None:
for value in self.right.in_order():
yield value
...
tree = Tree(...)
in_order_values = list(tree.in_order())
ten sposób don” t trzeba utworzyć listę, jeśli chcesz tylko iteracyjne nad wartościami:
for value in tree.in_order():
...
algorytm działa tak: generator pierwszy schodzi rekurencyjnie wzdłuż lewej gałęzi każdym węźle, dopóki nie natrafi jednego bez lewego pod- węzeł. Następnie generuje wartość bieżącego węzła. Potem robi to samo na prawym pod-węźle, ale zaczynając od bieżącego węzła, a nie węzła głównego. Jeśli założymy, że w drzewie nie ma cykli i nie ma nieskończonych gałęzi, to z pewnością będą to węzły liścia, tj. Węzły bez lewego lub prawego pod-węzła. Węzły IOW, dla których osiągnięto oba podstawowe przypadki (self.left/right is None
). Dlatego rekurencyjne wywołania powrócą, miejmy nadzieję, zanim skończy nam się pamięć lub osiągniemy limit stosu.
Pętla nad self.left/right.in_order()
jest to konieczne ze względu na fakt, że to, co wezwanie do in_order()
zwrotów jest generator, stąd nazwa generator funkcyjny. Zwrócony generator musi zostać jakoś wyczerpany, np. przez pętlę.W ciele pętli ponownie podnosimy wartości do góry o jeden poziom, na którym są ponownie ponawiane, aż osiągną najwyższy poziom. Tam używamy wartości.
Jeśli chcesz pobrać węzły samym sobą, a nie tylko pól ich wartości, można zrobić to tak:
class Tree(object):
...
def in_order(self):
if self.left is not None:
for node in self.left.in_order():
yield node
yield self # <-- yielding the node itself
if self.right is not None:
for node in self.right.in_order():
yield node
Prawdopodobnie chcesz to zrobić, ponieważ nie tylko można nadal uzyskać dostęp do wartości węzły:
for node in tree.in_order():
do_something_with(node.value)
ale również możesz robić, co chcesz z węzłami:
for node in tree.in_order():
whatever(node.some_other_attribute)
Gdzie jest wstępnie zdefiniowano listę zamówień, jaka jest struktura danych na wykresie? –