Обход в обратном порядке требует, чтобы вы печатали текущее значение узла только после обхода левого и правого поддеревьев. Вы используете стек для обхода только левого дерева и используете переменную current1
(последний напечатанный узел), чтобы знать, что теперь вы выходите из правого дерева, чтобы вы могли напечатать текущий узел.
Я бы переименовал current
в node
, current1
в last
(для последней печати), удалил функцию peek()
, чтобы просто ссылаться на stack[-1]
непосредственно как tos
(верхняя часть стека), и упростил ваш подход к:
def postorder_iterative(self):
node, last = self, None
stack = []
while True:
if node and node is not last:
# build up the stack from the left tree
stack.append(node)
node = node.leftChild
elif stack:
# no more left-hand tree to process, is there a right-hand tree?
tos = stack[-1]
if tos.rightChild and tos.rightChild is not node:
node = tos.rightChild
else:
# both left and right have been printed
node = last = stack.pop()
print(last.key)
else:
break
Однако все еще трудно понять, что происходит, поскольку связь между last
и точкой, где были обработаны левое и правое поддеревья, не совсем ясна.
Я бы использовал один стек с флагом состояния, чтобы отслеживать, где вы находитесь в процессе:
def postorder_iterative(self):
new, left_done, right_done = range(3) # status of node
stack = [[self, new]] # node, status
while stack:
node, status = stack[-1]
if status == right_done:
stack.pop()
print(node.key)
else:
stack[-1][1] += 1 # from new -> left_done and left_done -> right_done
# new -> add left child, left_done -> add right child
next_node = [node.leftChild, node.rightChild][status]
if next_node is not None:
stack.append((next_node, new))
Узлы проходят через три состояния, просто увеличивая флаг состояния. Они начинаются как новые узлы, затем продвигаются к левому, затем правому, и когда вершина стека находится в этом последнем состоянии, мы удаляем ее. из стека и вывести значение узла.
Находясь в состоянии new или left, мы добавляем левый или правый узел, если он есть, в стек как новый узел.
Другой подход помещает правое дерево в стек перед текущим узлом. Затем позже, когда вы вернетесь к текущему узлу, взяв его из стека, вы можете обнаружить случай, когда вам все еще нужно обработать правую часть, потому что вершина стека будет иметь правый узел. В этом случае вы заменяете вершину стека текущим узлом и продолжаете оттуда; позже вы вернетесь в то же место, и у вас больше не будет этого правого узла в верхней части стека, чтобы вы могли напечатать:
def postorder_iterative(self):
stack = []
node = self
while node or stack:
while node:
# traverse to the left, but add the right to the stack first
if node.rightChild is not None:
stack.append(node.rightChild)
stack.append(node)
node = node.leftChild
# left-hand tree traversed, time to process right or print
node = stack.pop()
if stack and node.rightChild is stack[-1]:
# right-hand tree present and not yet done, swap tos and node
node, stack[-1] = stack[-1], node
else:
print(node.key)
node = None
person
Martijn Pieters
schedule
11.02.2019