Trovando se BST 2 rappresentato da matrici sono isomorfi o meno

voti
0

1) Dato 2 array che contengono elementi di un albero binario completo (livello per livello), senza in realtà ricostruire un albero (cioè da solo facendo swap in un array), come posso trovare se quei 2 array sono isomorfi o no?

2) Una soluzione migliore se un albero isomorfo forma un binario Search Tree.

aggiornamento es

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

può essere rappresentato in array come 5 4 7 2 3 6 8

alberi isomorfi sono alberi che possono essere convertiti l'uno all'altro mediante rotazione intorno nodi

     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
È pubblicato 07/11/2011 alle 19:30
fonte dall'utente
In altre lingue...                            


4 risposte

voti
2

Si potrebbe fare un albero di passeggiata-ordine su entrambi contemporaneamente e verificare se gli elementi sono gli stessi.

Risposto il 07/11/2011 a 20:24
fonte dall'utente

voti
0

Partecipando (2) prima, coppie scambio di nodi - e loro discendenti - a ogni livello, se necessario trasformare ogni albero in un albero binario di ricerca, con nodi sinistra <= nodi destra. Questo richiederà tempo n log n. Una volta che avete fatto questo, se si ha un albero binario di ricerca e di un isomorfo albero con un albero binario di ricerca, ora avete due alberi binari di ricerca. Come sottolineato da yi_H, ciò significa che un albero camminata in ordine mostrerà gli stessi elementi nello stesso ordine se entrambi gli alberi sono isomorfi. Ma un albero di passeggiata-ordine, in un albero memorizzato in un array come nei tuoi esempi, è solo un modo peculiare di visitare tutti gli elementi della matrice, quindi se gli alberi sono isomorfi le due matrici devono essere identici.

Il modo più semplice per gestire una parte (1) è se si può trovare spazio aggiuntivo. Per il livello più basso di ogni albero, costruire una tabella di hash per ogni albero in possesso di foglie. Confrontare le due tabelle hash e uscire se non sono titolari lo stesso insieme di nodi. Dare ad ogni foglia un identificatore che lo identifica, in cui gli identificatori sono le stesse se le foglie sono gli stessi. Per i genitori di quelle foglie, costruire un'altra tabella hash, utilizzando i valori a ciascun genitore e gli identificatori di quei bambini. Ancora una volta, verificare che i due insiemi sono uguali e uscita in caso contrario. Assegnare ogni genitore un identificatore che è lo stesso se il valore in corrispondenza del nodo è lo stesso e gli identificatori dei suoi figli sono gli stessi. È possibile continuare in questo modo l'albero fino a raggiungere la radice. Se tutti i set sono gli stessi tutta la strada fino, si dispone di due alberi isomorfi, e gli identificatori che si danno la corrispondenza ad ogni livello. Questo è più complessa di una parte (1) e prende spazio in più, ma solo il tempo lineare.

Risposto il 08/11/2011 a 06:26
fonte dall'utente

voti
2

Per il primo problema:

Un po 'di notazione:

  • T0, T1 - alberi
  • valore (t) - il numero memorizzato nel nodo
  • a sinistra (t) - sottoalbero sinistro
  • a destra (t) - il sottoalbero destro

t1e t2sono isomorfi, sse t1e t2sono vuoti,

o value (t1) == value (t2)

e

left(t1)è isomorfo a left(t2)ed right(t1)è isomorfo a right(t2),

o left(t1)è isomorfo a right(t2)ed right(t1)è isomorfo aleft(t2)

Supponendo gli alberi sono memorizzati in un array, in modo tale che l'elemento 0 è la radice e se tè un indice di un nodo interno 2t+1e 2t+2sono indici dei suoi figli immediati attuazione semplice:

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

Per il secondo problema, ad ogni passo, si confronta il sottoalbero acon radice minore al sottoalbero bcon la radice più piccola e quindi il sottoalbero acon radice maggiore al sottoalbero bcon radice più grande (più piccola e più grande della corrente radici ae 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);
}
Risposto il 08/11/2011 a 15:41
fonte dall'utente

voti
0

Per BST:

  1. Prendere i primi elementi di entrambi gli array e partita. Se non uguale, allora BST non sono essere lo stesso.
  2. Trova i primi bambini di sinistra che non è stato digitalizzati (nelle posizioni leftPos1 e leftPos2) e partita. Se non abbinato poi la BST non sono gli stessi.
  3. Trova i primi bambini di destra che non è stato digitalizzati (nelle posizioni rightPos1 e rightPos2) e partita. Se non abbinato poi la BST non sono gli stessi.
  4. Se entrambi i figli a destra ea sinistra corrispondono, il eseguire le stesse operazioni in modo ricorsivo sul due coppie di sottoliste / sottostruttura (da leftPos1 e leftPos2) e (da rightPos1 e rightPos2). Il genitore di questi sottostruttura è il primo elemento della matrice.

Durante la ricerca i bambini sinistro e destro nella sottolista, ci possono essere elementi che sono già sottoposti a scansione. Per scoprire tali elementi, verificare che elemento che possa essere i figli della sottostruttura corrente. Se la sottostruttura attuale è al lato sinistro del genitore, quindi confrontare l'elemento con il genitore, se appartengono al lato destro poi ignorare questo 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;
}
Risposto il 16/03/2013 a 18:30
fonte dall'utente

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