Encontrando ya sea 2 BST representado por matrices son isomorfos o no

votos
0

1) Dado 2 matrices que contienen elementos de un árbol binario completo (nivel por nivel), sin tener que reconstruir un árbol (es decir, mediante permutas sólo se hacen en una matriz), ¿cómo puedo encontrar si esos 2 arrays son isomorfos o no?

2) Una solución mejor si un árbol isomorfo forma un árbol de búsqueda binaria.

actualización por ejemplo,

     5 
    / \
    4  7
   /\  /\
  2  3 6 8

puede ser representada en matriz como 5 4 7 2 3 6 8

árboles isomorfos son árboles que pueden ser convertidos el uno al otro por rotación alrededor de nodos

     5 
    / \
    4  7
   /\  /\
  2  3 6 8



     5 
    / \
    4  7
   /\  /\
  3  2 6 8



     5 
    / \
    4  7
   /\  /\
  3  2 8 6



     5 
    / \
    7  4
   /\  /\
  8  6 3 2
Publicado el 07/11/2011 a las 19:30
fuente por usuario
En otros idiomas...                            


4 respuestas

votos
2

Se podría hacer un recorrido del árbol en el orden de los dos al mismo tiempo y comprobar si los elementos son los mismos.

Respondida el 07/11/2011 a las 20:24
fuente por usuario

votos
0

Tomando la parte (2) primero, los pares de intercambio de nodos - y sus descendientes - en cada nivel, según sea necesario para activar cada árbol en un árbol de búsqueda binario, con nodos izquierda <= nodos adecuados. Esto tomará tiempo n log n. Una vez hecho esto, si usted tenía un árbol de búsqueda binaria y una isomorfo árbol con un árbol de búsqueda binaria, que ahora tiene dos árboles binarios de búsqueda. Como ha señalado yi_H, esto significa que un paseo árbol en orden se muestran los mismos elementos en el mismo orden si ambos árboles son isomorfos. Sin embargo, un recorrido del árbol en orden, en un árbol almacenada en una matriz como en sus ejemplos, es sólo una forma peculiar de visitar todos los elementos de la matriz, por lo que si los árboles son isomorfos las dos matrices deben ser idénticos.

La forma más fácil de manejar parte (1) es si se puede encontrar un espacio adicional. Para el nivel más bajo de cada árbol, construir una tabla hash para cada árbol que sostiene las hojas. Compare las dos tablas hash y de salida si ellos no tienen el mismo conjunto de nodos. Dé a cada hoja un identificador que identifica, donde los identificadores son los mismos si las hojas son los mismos. Para los padres de esas hojas, construir otra tabla hash, utilizando los valores en cada uno de los padres y los identificadores de esos niños. Una vez más, comprobar que los dos conjuntos son los mismos y de salida si no. Asignar cada padre un identificador que es la misma si el valor en el nodo es el mismo y los identificadores de sus hijos son los mismos. Puede continuar en este camino hasta el árbol hasta llegar a la raíz. Si todos los conjuntos son los mismos todo el camino hasta, tiene dos árboles isomorfos, y los identificadores de darle la correspondencia en cada nivel. Esto es más compleja que la parte (1) y toma más espacio, pero sólo el tiempo lineal.

Respondida el 08/11/2011 a las 06:26
fuente por usuario

votos
2

Para el primer problema:

Un poco de notación:

  • T0, T1 - árboles
  • valor (t) - el número almacenado en el nodo
  • izquierda (t) - el subárbol izquierdo
  • derecha (t) - el subárbol derecho

t1y t2son isomorfos, si y sólo si t1y t2están vacíos,

o value (t1) == value (t2)

y

o bien left(t1)es isomorfo left(t2)y right(t1)es isomorfo right(t2),

o left(t1)es isomorfo a right(t2)y right(t1)es isomorfo aleft(t2)

Suponiendo que los árboles se almacenan en un arrays, que tal elemento 0 es la raíz y, y si tes un índice de un nodo interno2t+1 y 2t+2son los índices de sus hijos inmediatos, implementación directa:

#include <stdio.h>

#define N 7

int a[] = { 5, 4, 7, 2, 3, 6, 8 };
int b[] = { 5, 7, 4, 6, 8, 2, 3 };

int
is_isomorphic (int t1, int t2)
{
  if (t1 >= N && t2 >= N)
    return 1;

  if (a [t1] != b [t2])
    return 0;

  return ((is_isomorphic (2*t1 + 1, 2*t2 + 1)
           && is_isomorphic (2*t1 + 2, 2*t2 + 2))
          || (is_isomorphic (2*t1 + 1, 2*t2 + 2)
              && is_isomorphic (2*t1 + 2, 2*t2 + 1)));
}

int main ()
{
  printf ("%s\n", (is_isomorphic (0, 0) ? "yes" : "no"));
  return 0;
}

Para el segundo problema, en cada paso, comparamos el sub-árbol de ala raíz más pequeña a la sub-árbol de bla raíz más pequeña y luego el sub-árbol de ala raíz más grande para el subárbol de bla raíz más grande (más pequeño y más grande que el actual raíces de ay b).

int
is_isomorphic_bst (int t1, int t2)
{
  if (t1 >= N && t2 >= N)
    return 1;

  if (a [t1] != b [t2])
    return 0;

  int t1l, t1r, t2l, t2r;
  if (a [2*t1 + 1] < a [t1] && a [t1] < a [2*t1 + 2])
    {
      t1l = 2*t1 + 1;
      t1r = 2*t1 + 2;
    }
  else if (a [2*t1 + 1] > a [t1] && a [t1] > a [2*t1 + 2])
    {
      t1l = 2*t1 + 2;
      t1r = 2*t1 + 1;
    }
  else
    return 0;

  if (b [2*t2 + 1] < b [t2] && b [t2] < b [2*t2 + 2])
    {
      t2l = 2*t2 + 1;
      t2r = 2*t2 + 2;
    }
  else if (b [2*t2 + 1] > b [t2] && b [t2] > b [2*t2 + 2])
    {
      t2l = 2*t2 + 2;
      t2r = 2*t2 + 1;
    }
  else
    return 0;

  return is_isomorphic_bst (t1l, t2l) && is_isomorphic_bst (t1r, t2r);
}
Respondida el 08/11/2011 a las 15:41
fuente por usuario

votos
0

Para BST:

  1. Dar los primeros elementos de ambas matrices y fósforo. Si no iguales, entonces no están BST ser el mismo.
  2. Encuentra los primeros niños que quedan que no ha sido escaneados (en las posiciones leftPos1 y leftPos2) y fósforo. Si no coinciden, BST no son iguales.
  3. Encuentra los primeros niños derecha que no ha sido escaneados (en las posiciones rightPos1 y rightPos2) y fósforo. Si no coinciden, BST no son iguales.
  4. Si los dos hijos izquierdo y derecho coinciden, la realizan las mismas operaciones de forma recursiva en el doble par de sublistas / subárbol (de leftPos1 y leftPos2) y (desde rightPos1 y rightPos2). El padre de estos sub-árbol es el primer elemento de la matriz.

Si bien la búsqueda de los hijos izquierdo y derecho en la lista secundaria, puede haber elementos que ya se han escaneado. Para averiguar tales elementos, comprobar que el elemento que puede ser los hijos del subárbol actual. Si el subárbol actual está al lado izquierdo de la matriz, a continuación, comparar el elemento con el padre, si pertenecen a la derecha y luego ignorar ese elemento.

#include <stdio.h>

#define BOOL int
#define TRUE 1
#define FALSE 0

BOOL isLeft(int parent, int child) {
    return child <= parent;
}

BOOL isRight(int parent, int child) {
    return child > parent;
}

BOOL isBelongToChild(int parent, int child, int value) {
    if (isLeft(parent, child) && (isLeft(parent, value))) {
        return TRUE;
    }
    if (isRight(parent, child) && (isRight(parent, value))) {
        return TRUE;
    }
    return FALSE;
}

int getLeftPosition(int * array, int size, int parent, BOOL parentExists) {
    int i;

    int first = *array;
    for (i = 1; i < size; i++) {
        int value = *(array + i);
        if (! isBelongToChild(parent, first, value)) {
            continue;
        }
        if (isLeft(first, value)) {
            return i;
        }
    }
    return -1;
}

int getRightPosition(int * array, int size, int parent, BOOL parentExists) {
    int i;

    int first = *array;
    for (i = 1; i < size; i++) {
        int value = *(array + i);
        if (! isBelongToChild(parent, first, value)) {
            continue;
        }
        if (isRight(first, value)) {
            return i;
        }
    }
    return -1;
}

BOOL areSame(int * array1, int pos1, int * array2, int pos2) {
    if (pos1 == -1 && pos2 == -1) {
        return TRUE;
    } else if (*(array1 + pos1) == *(array2 + pos2)) {
        return TRUE;
    } else {
        return FALSE;
    }
}

BOOL isSameBst(int * array1, int size1, int * array2, int size2, int parent, BOOL parentExists) {
    if (0 == size1 && 0 == size2) {
        return TRUE;
    }
    if (*array1 != *array2) {
        return FALSE;
    }

    int leftPos1 = getLeftPosition(array1, size1, parent, parentExists);
    int leftPos2 = getLeftPosition(array2, size2, parent, parentExists);
    if (! areSame(array1, leftPos1, array2, leftPos2)) {
        return FALSE;
    }
    int rightPos1 = getRightPosition(array1, size1, parent, parentExists);
    int rightPos2 = getRightPosition(array2, size2, parent, parentExists);
    if (! areSame(array1, rightPos1, array2, rightPos2)) {
        return FALSE;
    }

    if (leftPos1 > -1) {
        int result = isSameBst((array1 + leftPos1), size1 - leftPos1, (array2 + leftPos2), size2 - leftPos2, *array1, TRUE);
        if (FALSE == result) {
            return FALSE;
        }
    }
    if (rightPos1 > -1) {
        int result = isSameBst((array1 + rightPos1), size1 - rightPos1, (array2 + rightPos2), size2 - rightPos2, *array1, TRUE);
        if (FALSE == result) {
            return FALSE;
        }
    }
    return TRUE;
}

int main ()
{
    int a[] = { 5, 6, 2, 7, 4 };
    int b[] = { 5, 6, 7, 2, 4 };
    printf ("%s\n", (isSameBst(a, 5, b, 5, 0, FALSE) ? "yes" : "no"));
    return 0;
}
Respondida el 16/03/2013 a las 18:30
fuente por usuario

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