Comparación de los árboles utilizando el enfoque sugerido por la canonización @mcdowella . La diferencia es que mi enfoque no requiere O(N)número WRT memoria adicional de nodos en el árbol:
# in Python
from collections import namedtuple
from itertools import chain
# Tree is either None or a tuple of its value and left, right trees
Tree = namedtuple('Tree', 'value left right')
def canonorder(a, b):
"""Sort nodes a, b by their values.
`None` goes to the left
"""
if (a and b and a.value > b.value) or b is None:
a, b = b, a # swap
return a, b
def canonwalk(tree, canonorder=canonorder):
"""Yield all tree nodes in a canonical order.
Bottom-up, smaller children first, None is the smallest
"""
if tree is not None:
children = tree[1:]
if all(t is None for t in children): return # cut None leaves
children = canonorder(*children)
for child in chain(*map(canonwalk, children)):
yield child
yield tree
canonwalk()requiere O(N*M)pasos y O(log(N)*M)memoria para producir todos los nodos en un árbol, donde Nes el número total de nodos, Mnúmero de niños cada nodo tiene (es 2 para árboles binarios).
canonorder()puede generalizarse fácilmente para cualquier nodo de la representación y cualquier número de hijos. canonwalk()sólo requiere que un árbol puede tener acceso a sus hijos inmediatos como una secuencia.
La función de comparación que llama canonwalk():
from itertools import imap, izip_longest
unset = object()
def cmptree(*trees):
unequal = False # allow root nodes to be unequal
# traverse in parallel all trees under comparison
for nodes in izip_longest(*imap(canonwalk, trees), fillvalue=unset):
if unequal:
return False # children nodes are not equal
if any(t is unset for t in nodes):
return False # different number of nodes
if all(t is not None for t in nodes):
unequal = any(nodes[-1].value != t.value for t in nodes)
else: # some are None
unequal = any(t is not None for t in nodes)
return True # equal
Ejemplo
5 6
/ \ / \ they are equal.
1 2 2 1
/ \ / /
3 4 4 3
tree1 = Tree(5,
Tree(1,
Tree(3, None,None), None),
Tree(2,
None, Tree(4, None, None)))
tree2 = Tree(6,
Tree(2, Tree(4, None, None), None),
Tree(1, Tree(3, None, None), None))
print cmptree(tree1, tree2)
Salida
True