Zjištění, zda 2 BST zastoupena poli jsou isomorphic, či nikoli

hlasů
0

1) Vzhledem k tomu, 2 pole, které obsahují prvky kompletní binární strom (úroveň podle úrovně), aniž by ve skutečnosti rekonstrukci stromu (tj jen to swapy v řadě), jak mohu zjistit, zda jsou tyto 2 sady jsou isomorphic, nebo ne?

2) Lepším řešením, pokud jeden isomorphic strom tvoří binární vyhledávací strom.

aktualizace např

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

mohou být reprezentovány v poli jako 5 4 7 2 3 6 8

Izomorfní stromy jsou stromy, které mohou být převedeny na sobě prostřednictvím otáčení kolem uzly

     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
Položena 07/11/2011 v 19:30
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
2

Dalo by se to in-pořadí stromu vycházce na oba současně a zkontrolovat, zda tyto prvky jsou stejné.

Odpovězeno 07/11/2011 v 20:24
zdroj uživatelem

hlasů
0

Podílet (2) První swapové páry uzlů - a jejich potomci - na každé úrovni, podle potřeby obrátit každý strom do binárního vyhledávacího stromu, s levým uzly <= vpravo uzlů. To bude nějakou dobu trvat n log n. Poté, co jste udělal, když jste měli binární vyhledávací strom a strom izomorfní s binárního vyhledávacího stromu, máte nyní dva binární vyhledávací stromy. Jak poukázal yi_H, to znamená, že in-pořadí stromu vycházce se objeví stejné prvky ve stejném pořadí, pokud jsou oba stromy jsou izomorfní. Ale in-pořadí stromu vycházce, na stromě uložena do pole jako ve svých příkladech je jen zvláštní způsob návštěvě všechny prvky pole, takže v případě, že stromy jsou isomorphic obě pole musí být identické.

Nejjednodušší způsob, jak zvládnout část (1) je, pokud můžete najít další prostor. U nejnižší úrovně každého stromu, stavět hash tabulku pro každý strom drží listy. Porovnat dva hash tabulky a odchod v případě, že nemají stejnou sadu uzlů. Dát každý list identifikátor, který jej identifikuje, kde identifikátory jsou stejné v případě, že listy jsou stejné. Pro rodiče těchto listů, stavět další hashovací tabulky, pomocí hodnot u každého z rodičů a identifikátory těch dětí. Znovu zkontrolujte, zda jsou dva soubory jsou stejné a výjezd, pokud ne. Přiřazení každého z rodičů identifikátor, který je stejný, pokud je hodnota v uzlu je stejná a identifikátory svých dětí jsou stejné. Můžete pokračovat v této cestě vzhůru stromu, dokud se nedostanete kořen. Pokud jsou všechny soubory jsou stejné po celou cestu nahoru, máte dvě isomorphic stromy a identifikátory vám korespondenci na každé úrovni. To je mnohem složitější, než části (1) a má více prostoru, ale jen lineární čas.

Odpovězeno 08/11/2011 v 06:26
zdroj uživatelem

hlasů
2

Pro první problém:

Trochu notace:

  • t0, t1 - stromy
  • hodnota (t) - číslo uložené v uzlu
  • levé (t) - levá podstromu
  • vpravo (t) - právo podstromu

t1a t2jsou izomorfní, iff t1a t2jsou prázdné,

nebo value (t1) == value (t2)

a

Buď left(t1)je izomorfní left(t2)a right(t1)je isomorfní right(t2),

nebo left(t1)je izomorfní right(t2)a right(t1)je isomorfníleft(t2)

Za předpokladu, že stromy jsou uloženy v poli, takže prvek 0 je kořen, a, a pokud tje index vnitřního uzlu 2t+1a 2t+2jsou indexy jeho bezprostředním dětí, přímočará implementace:

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

Pro druhý problém, při každém kroku, porovnáme podstromu as menším root na podstromu bs menším kořene a pak podstromu as větší root na podstromu bs větším kořenovým (menší a větší než proud kořeny aa 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);
}
Odpovězeno 08/11/2011 v 15:41
zdroj uživatelem

hlasů
0

Pro BST:

  1. Podniknout první prvky obou polí a utkání. Pokud tomu tak není rovno pak BST se nebudou stejné.
  2. Najít první vlevo děti , které nebyly naskenovány (v polohách leftPos1 a leftPos2) a utkání. Pokud tomu tak není uzavřeno poté BST nejsou stejné.
  3. Najít Prvním právem dětí , které nebyly naskenovány (v polohách rightPos1 a rightPos2) a utkání. Pokud tomu tak není uzavřeno poté BST nejsou stejné.
  4. V případě shody obou levý a pravý děti se provádět stejné operace rekurzivně na dva páry sublists / podstromu (od leftPos1 a leftPos2) a (od rightPos1 a rightPos2). Mateřská těchto podstromu je první prvek pole.

Zatímco hledá levý a pravý děti do dílčí seznam, může být prvky, které jsou již naskenované. Chcete-li zjistit takové prvky, ověřit, že prvek, který může být pro děti aktuálního podstromu. Pokud je aktuální podstrom je na levé straně mateřské společnosti, pak porovnat prvek s rodiči, pokud to patří k pravé straně, pak tento prvek ignorovat.

#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;
}
Odpovězeno 16/03/2013 v 18:30
zdroj uživatelem

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