2 árboles binarios son iguales o no

votos
7

Duplicar posibles:
Determinar si dos árboles binarios son iguales

Tienes una entrevista ayer, una pregunta me consiguió, aquí está:

Descripción

Hay 2 binary trees, comprobar si son iguales.

Ellos son iguales si y sólo si tree1->child == tree2->child, y un árbol de la izquierda y la derecha children can be swapped with each other.

Por ejemplo:

    5     6
   / \   / \           they are equal.
   1 2   2  1

    5         6
   / \       / \           they are equal.
  1   2     2   1
 /     \   /    / 
3       4 4     3

Cualquier ideas son apreciadas.

Publicado el 12/10/2011 a las 01:18
fuente por usuario
En otros idiomas...                            


6 respuestas

votos
9

operadores de igualdad son transitivos: Si A = B, y B = C, entonces A = B = C de modo que A = C.

operadores de igualdad son reflexivos: A = A, B = B, y C = C no importa cuáles son sus valores.

operadores de igualdad son simétricas. Si A = B, entonces B = A. (No importa qué orden que se encuentran.)

Ahora, echar un vistazo a la definición que le dio:

Un árbol es igual a otro árbol si los niños son iguales. Veamos. Podemos suponer que los nodos están siendo comparados en la parte inferior, o de lo contrario la definición es bastante inútil. Pero ellos no se molestan en decir cómo resolver esa comparación, y toda la definición que le dio gira en torno a ella.

En resumen, se trata de una cuestión de mierda.

Veamos lo que sucede si decidimos que queremos tratar de desentrañar la cuestión, sin embargo.

Pero espera, sino que también le dicen que los dos hijos de cualquier árbol se pueden intercambiar. Esto añade la restricción de que cualquier árbol que es igual a cualquier otra cosa (incluido él mismo) debe ser igual a su imagen especular. Y cualquier variación de los niños sus subárboles se intercambian.

Y recordar que esto se supone que es una búsqueda árbol. Por lo tanto, podemos suponer que probablemente dos diferentes árboles de búsqueda que son procesados por el mismo algoritmo deben dar el mismo resultado si son iguales. Por lo tanto, si cambiamos alrededor de los elementos de un árbol, entonces el tiempo de búsqueda se vería afectada. Así, los árboles que no tienen todos los nodos en lugar no son iguales entre sí.

Poner que en conjunto con la propiedad "swap" de esta igualdad, podemos ver que no es una definición válida de la igualdad. (Si tratamos de aplicarla, a continuación, resulta que sólo los árboles que tienen el mismo nodo para cada nodo en un nivel particular son iguales, y sólo a ellos mismos, lo que rompe la parte reflexividad de un operador de igualdad.)

Respondida el 12/10/2011 a las 01:24
fuente por usuario

votos
3

Si implementa su definición de "igualdad" con flip-invariancia, se violaría la definición de igualdad. La definición ni siquiera tiene sentido, porque no es así como árboles binarios de búsqueda son iguales (a menos que cada nodo tiene un puntero a la que subárbol es "mayor" y que es "menor").

Tiene dos opciones de definiciones razonables:

  1. topológico (flip-agnóstico) equivalencia (en cuyo caso no se puede llamar un "árbol de búsqueda binaria" porque no está ordenadas):

    tree1==tree2 medio set(tree1.children)==set(tree2.children)

  2. normal de árbol de búsqueda (flip-cuidado) equivalencia:

    tree1==tree2 medio list(tree1.children)==list(tree2.children)

Para los árboles binarios, las definiciones anteriores funcionarán como está escrito en cualquier lenguaje que soporte el listy settipos de datos (conjuntos Python ahogarse sin embargo, en los tipos de datos unhashable). Sin embargo, a continuación son algunos C definiciones / Java-como más detallado y feas:

  1. equivalencia topológica:

    t1==t2 medio (t1.left==t2.left and t1.right==t2.right) or (t1.left==t2.right and t1.right==t2.left)

  2. equivalencia árbol ordenada:

    t1==t2 medio (t1.left==t2.left and t1.right==t2.right)

Las definiciones anteriores son recursivo; es decir, que asumen la igualdad se ha definido para las sub-estructuras y bases casos ya, los cuales tiene.


nota al margen:

Cita: tree1-> niño == tree2-> niño

Esto no es una declaración válida, porque un nodo del árbol no tiene un solo hijo.

Respondida el 12/10/2011 a las 02:20
fuente por usuario

votos
7

No creo que esta es una pregunta razonable. Una solución simple es recursivo

boolean equals(x, y)
{
  if (x == null)
  {
    return y == null;
  }
  if (y == null)
  {
    return false;
  }
  if (x.val != y.val)
  {
    return false;
  }
  if (equals(x.left, y.left) && equals(x.right, y.right))
  {
    return true;
  }
  if (equals(x.left, y.right) && equals(x.right, y.left))
  {
    return true;
  }
  return false;
}

Esto puede ser muy caro, por ejemplo en el caso cuando tenemos dos árboles de gran tamaño de forma similar en el que todos los nodos que no son hojas tienen el mismo valor asociado y los nodos hoja de uno son una permutación de los nodos hoja de otro.

Para superar esto, en primer lugar, el cambio podría izquierda y derecha según sea necesario para que la izquierda <derecha, por alguna definición recursiva de <. Esto también podría ser costoso, pero mucho menos que el control de todas las permutaciones, y creo que una opción de definición de <ayudaría. Esto permitiría que compruebe si hay igualdad con una definición común.

Esta noción de http://en.wikipedia.org/wiki/Canonicalization seguido por la igualdad ordinaria también resuelve preguntas sobre si realmente tienen una relación de equivalencia. Una relación de equivalencia es equivalente a una partición. La igualdad ordinaria es, obviamente, una partición. Si se compara x e y mediante la comparación de f (x) y f (y) seguido de una relación de equivalencia tiene una partición de X e Y, y por lo tanto una relación de equivalencia.

Pensar más en esto, creo que la manera de hacer que sea canonicalisation o igualdad-prueba razonablemente eficiente es trabajar de abajo hacia arriba, anotar cada nodo con un token cuyo valor refleja el resultado de la comparación con otros nodos, por lo que se puede comparar nodos y los subárboles por debajo de ellos, que se compara fichas.

Así que el primer paso para la igualdad es que por ejemplo, usar una tabla hash para anotar cada hoja con fichas que son iguales sólo cuando los valores en las hojas son iguales. Entonces, para los nodos cuyos hijos sólo son las hojas, por ejemplo, usar una tabla hash para asignar nuevas fichas de manera que las fichas en los nodos son iguales sólo cuando las hojas, en su caso, por debajo de los nodos partido. A continuación, puede ir un paso más, y esta vez se puede comparar fichas en nodos hijos en lugar de manera recursiva por el árbol allí. El costo de la asignación de fichas de esta manera debe ser lineal en el tamaño de los árboles en cuestión. En la parte superior se puede comparar árboles simplemente mediante la comparación de las fichas en la raíz.

Respondida el 12/10/2011 a las 06:57
fuente por usuario

votos
0

He leído las preguntas como: dado dos árboles binarios, para cada profundidad en el árbol, averiguar si conjunto de sus hijos están cubiertos en el otro.

Esto puede ser codificado relativamente fácil.

Respondida el 12/10/2011 a las 12:30
fuente por usuario

votos
0

Solución sin recursividad en Ruby

def same? top_t1, top_t2
  for_chek << [top_t1, top_t2]   # (1) put task for check into queue

  while t1,t2 = for_check.shift  # (2)
    return false unless t1.children.count == t2.children.count  # generally for non-binary tree, but also needed for controlling of nil children
    break if t1.children.empty?

    t1_children = t1.children.sort # this is sorted arrays
    t2_children = t2.children.sort # of childrens      
    return false unless t1_children == t2_children  # (3)

    0.upto(t1_children.count - 1) do |i|
      for_check << [t1_children[i], t2_children[i]]  # put equivalent child pairs into queue
    end
  end
  return true
end

consejos de sintaxis Ruby:

  • (1) elemento de puesta en matriz: arr << elem; en este caso for_checkes matriz de matrices
  • (2) la asignación en paralelo: t1,t2 = [item1, item2]. Igual quearr = [item1, item2]; t1 = arr[0]; t2 = arr[1]
  • (3) t1_children == t2_childrenasumido comportamiento correspondiente de == para este tipo de objetos. Más detallado será t1_children.map { |el| el.val } == t2_children.map { |el| el.val }- que aquí mapproduce variedad de Vals.
Respondida el 15/10/2011 a las 16:17
fuente por usuario

votos
1

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
Respondida el 15/10/2011 a las 21:10
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more