Confronta alberi che utilizzano l'approccio suggerito da canonizzazione @mcdowella . La differenza è che il mio approccio non richiede O(N)ulteriore numero WRT memoria di nodi dell'albero:
# 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()richiede O(N*M)passi e O(log(N)*M)memoria per produrre tutti i nodi in un albero, dove Nè il numero totale di nodi, Mnumero di figli ciascun nodo contiene (è 2 per alberi binari).
canonorder()potrebbe essere facilmente generalizzato per qualsiasi rappresentazione nodi e qualsiasi numero di figli. canonwalk()richiede solo che un albero può accedere ai suoi figli immediati come una sequenza.
La funzione di confronto che chiama 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
Esempio
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)
Produzione
True