Znalezienie czy 2 BST reprezentowane przez macierze są izomorficzne, czy nie

głosy
0

1) Ze względu na 2 tablice zawierające elementy kompletnego binarne drzewo (z poziomu na poziom), bez faktycznie rekonstrukcji drzewa (czyli tylko o robienie swapów w tablicy), jak mogę znaleźć, czy te 2 tablice są izomorficzne, czy nie?

2) Lepszym rozwiązaniem jeśli izomorficzna tworzy drzewo binarne drzewo poszukiwań.

aktualizacja np

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

mogą być reprezentowane w tablicy jako 5 4 7 2 3 6 8

Izomorficzne drzewa to drzewa, które mogą być przekształcone w siebie przez obracanie wokół węzłów

     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
Utwórz 07/11/2011 o 19:30
źródło użytkownik
W innych językach...                            


4 odpowiedzi

głosy
2

Można zrobić drzewo spacer zamówienie na nich obu jednocześnie i sprawdzić, czy elementy są takie same.

Odpowiedział 07/11/2011 o 20:24
źródło użytkownik

głosy
0

Biorąc część (2) w pierwszej pary swap węzłów - oraz ich potomstwo - na każdym poziomie, a niezbędnych do przekształcenia każdego drzewa do poszukiwania binarnego drzewa, z lewej węzłów <= prawa węzłów. To zajmie czasu n log n. Gdy już to zrobisz, jeśli miał binarne drzewo wyszukiwania i izomorficzna drzewo z wyszukiwania binarnego drzewa, masz teraz dwa drzewa binarne wyszukiwania. Jak podkreślił yi_H, oznacza to, że drzewo spacer zamówienie pokaże te same elementy w tej samej kolejności, jeśli oba drzewa są izomorficzne. Ale drzewo spacer zamówienie, w drzewie przechowywane w tablicy, jak w swoich przykładach, jest tylko swoistym sposobem na odwiedzenie wszystkich elementów tablicy, więc jeśli drzewa są izomorficzne dwie tablice muszą być identyczne.

Najprostszym sposobem, aby obsłużyć część (1) to jeśli można znaleźć dodatkową przestrzeń. Na najniższym poziomie każdego drzewa, zbudować tabeli mieszania na każdym drzewie gospodarstwa liści. Porównać dwie tabele mieszania i wyjść, jeśli nie posiadają one ten sam zestaw węzłów. Daj każdy liść identyfikator, który identyfikuje go, gdzie identyfikatory są takie same, czy liście są takie same. Dla rodziców tych liści, budowa kolejnego tabeli mieszania, przy użyciu wartości z każdego z rodziców i identyfikatory tych dzieci. Ponownie sprawdzić, czy oba zestawy są takie same i wyjście, jeśli nie. Każdy rodzic przypisać identyfikator, który jest taki sam, jeśli wartość w węźle jest taka sama i identyfikatory jej dzieci są takie same. można prowadzić w ten sposób się drzewa aż do korzenia. Jeżeli wszystkie zestawy są takie same aż do góry, masz dwie izomorficzne drzew i identyfikatory daje korespondencji na każdym poziomie. Jest to bardziej skomplikowane, niż części (1) oraz zajmuje dodatkowej przestrzeni, ale tylko czas liniowej.

Odpowiedział 08/11/2011 o 06:26
źródło użytkownik

głosy
2

Dla pierwszego problemu:

Trochę notacji:

  • t0, t1 - drzewa
  • Wartość (T) - ilość przechowywana w węźle
  • lewo (t) - lewą Poddrzewo
  • prawo (t) - prawo Poddrzewo

t1i t2są izomorficzne, IFF t1i t2są puste,

lub value (t1) == value (t2)

i

albo left(t1)jest izomorficzna left(t2)i right(t1)jest izomorficzna right(t2),

lub left(t1)jest izomorficzna right(t2)i right(t1)jest izomorficznaleft(t2)

Zakładając, że drzewa są przechowywane w tablicach, tak, że element 0 jest korzeniem i jeśli tjest indeks węzła wewnętrznego 2t+1i 2t+2są indeksy jej bezpośrednimi dzieci, prosta realizacja:

#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;
}

Dla drugiego problemu, na każdym kroku, porównamy poddrzewa az mniejszym korzenia do poddrzewa bz mniejszych korzeni i wtedy poddrzewa az większym korzenia do poddrzewa bz większym root (mniejszy i większy niż prąd korzenie ai 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);
}
Odpowiedział 08/11/2011 o 15:41
źródło użytkownik

głosy
0

Dla BST:

  1. Podjąć pierwsze elementy obu tablic i meczu. Jeśli nie równa następnie BST nie być takie same.
  2. Znajdź w pierwszą w lewo dzieci , które nie zostały zeskanowane (w pozycjach leftPos1 i leftPos2) i meczu. Jeżeli nie odpowiadają wtedy BST nie są takie same.
  3. Znajdź w pierwszą w prawo dzieci , które nie zostały zeskanowane (w pozycjach rightPos1 i rightPos2) i meczu. Jeżeli nie odpowiadają wtedy BST nie są takie same.
  4. Jeżeli obie lewe i prawe dzieci zgodne, należy wykonać te same operacje rekurencyjnie na dwie pary podlist / poddrzewa (od leftPos1 i leftPos2) i (od rightPos1 i rightPos2). Rodzic tych poddrzewem jest pierwszy element tablicy.

Podczas poszukiwania lewy i prawy dzieci w podmenu, mogą być elementy, które są już zeskanowane. Aby dowiedzieć się takie elementy, sprawdzić, czy element, który może mieć dzieci bieżącego poddrzewa. Jeśli bieżący poddrzewo jest na lewej stronie rodzica, a następnie porównać element z rodzicem, jeśli należą do prawej strony, a następnie ignorować tego elementu.

#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;
}
Odpowiedział 16/03/2013 o 18:30
źródło użytkownik

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