Если мы начнем с простого рекурсивного алгоритма postorder,
def postorder1(node, f):
# a:
if node is None:
return None
postorder1(node.left, f)
# b:
postorder1(node.right, f)
# c:
f(node)
можно измельчить функцию на три части «а», «б» и «с», а затем наивно переводить это в итеративный алгоритм с помощью эмуляции виртуального стека вызовов:
def postorder2(node, f):
stack = [("a", node)]
while stack:
go, node = stack.pop()
if go == "a":
if node is not None:
stack.append(("b", node))
stack.append(("a", node.left))
elif go == "b":
stack.append(("c", node))
stack.append(("a", node.right))
elif go == "c":
f(node)
из этого мы наблюдаем, что стек может быть изменены только в одном из трех способов:
[…, a] → […, b, a]
[…, b] → […, c, a]
[…, c] → […]
Это означает, что:
- «а» может появиться только максимум один раз в верхней части стека, в то время как
- «б» и «в» и появляются любое количество раз в середине стека, возможно, чередуется.
Поэтому нам не нужно хранить «a» внутри стека - достаточно одной переменной для хранения «a». Это позволяет упростить наивный итерационный алгоритм в более традиционную форму:
def postorder3(node, f):
stack = []
while True:
if node:
stack.append((True, node))
node = node.left
elif stack:
left, top = stack.pop()
if left:
stack.append((False, top))
node = top.right
else:
f(top)
else:
break
Логический флаг на стопке «посетил флаг». В этом примере мы не храним флаг непосредственно на узлах, а внутри нашего стека, но сетевой эффект тот же. В некоторых вариантах алгоритма вместо этого используется переменная «последний посещенный узел», но для этого требуется способ сравнения узлов для «identity» (указатель/ссылочное равенство), которые мы здесь не предполагаем.
Этот флаг является частью алгоритма, поскольку, как отмечалось в нашем анализе ранее, записи «b» и «c» в стеке могут отображаться совершенно произвольно. Нам нужно вид информации, чтобы рассказать нам, следует ли нам перемещаться вправо или звонить по телефону f
.
Доступны ли указатели или ссылки на родительские узлы или вам нужен явный стек? –