Das Finden, ob 2 BST vertreten durch Arrays sind isomorph oder nicht

stimmen
0

1) Bei zwei Arrays Elemente eines kompletten Binärbaum (Ebene für Ebene enthält), ohne tatsächlich einen Baum (dh durch nur tun Swaps in einem Array) zu rekonstruieren, wie kann ich feststellen, ob diese 2-Arrays sind isomorph oder nicht?

2) Eine bessere Lösung, wenn man isomorph Baum bildet ein binärer Suchbaum.

Update zB

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

kann in der Anordnung dargestellt werden, wie 5 4 7 2 3 6 8

Isomorph Bäume sind Bäume, die miteinander durch eine Drehung um Knoten umgewandelt werden können

     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
Veröffentlicht am 07/11/2011 um 19:30
quelle vom benutzer
In anderen Sprachen...                            


4 antworten

stimmen
2

Sie könnten einen in Ordnung Baum zu Fuß auf beide gleichzeitig tun und prüfen Sie, ob die Elemente gleich sind.

Beantwortet am 07/11/2011 um 20:24
quelle vom benutzer

stimmen
0

Dabeisein (2) erster, Swap-Paare von Knoten - und ihre Nachkommen - auf jeder Ebene, wie notwendig, jeden Baum in einen binären Suchbaum zu drehen, mit dem linken Knoten <= rechte Knoten. Dies wird einige Zeit dauern n log n. Sobald Sie dies getan haben, wenn Sie einen binären Suchbaum und einen Baum isomorph mit einem binären Suchbaum haben, haben Sie jetzt zwei binäre Suchbäume. Wie durch yi_H wies darauf hin, bedeutet dies, dass ein in Ordnung wird Baum zu Fuß der gleichen Elemente in der gleichen Reihenfolge zeigen, wenn beiden Bäume isomorph sind. Aber ein in Ordnung Baum zu Fuß, in einem Baum in einem Array gespeichert, wie in Ihren Beispielen ist nur eine eigentümliche Art und Weise alle Elemente des Arrays zu besuchen, so dass, wenn die Bäume sind isomorph die beiden Arrays müssen identisch sein.

Der einfachste Weg, Teil (1) zu handhaben ist, wenn Sie zusätzlichen Platz finden können. Für die unterste Ebene jeden Baum, eine Hash-Tabelle für jeden Baum bauen, um die Blätter zu halten. Vergleichen Sie die beiden Hash-Tabellen und Ausgang, wenn sie den gleichen Satz von Knoten nicht halten. Geben Sie jedes Blatt eine Kennung, die sie identifiziert, wo die Kennungen sind die gleiche, wenn die Blätter gleich sind. Für die Eltern jener Blätter, bauen eine andere Hash-Tabelle, die Werte an jedem Elternteil und die Kennungen dieser Kinder verwenden. Wieder zu überprüfen, dass die beiden Sätze die gleiche und Ausfahrt sind, wenn nicht. Vergeben jeden Elternteil eine Kennung, die die gleiche, wenn der Wert an dem Knoten das gleiche ist und die Kennungen seiner Kinder sind gleich. Sie können auf den Baum auf diese Weise weitermachen, bis Sie die Wurzel erreichen. Wenn alle Sätze auf die gleiche ganzen Weg sind, haben Sie zwei isomorph Bäume, und die Kennungen geben Sie die Korrespondenz auf jeder Ebene. Dies ist komplexer als Teil (1) und nimmt besonders viel Platz, aber nur lineare Zeit.

Beantwortet am 08/11/2011 um 06:26
quelle vom benutzer

stimmen
2

Für das erste Problem:

Ein bisschen Schreibweise:

  • t0, t1 - Bäume
  • Wert (t) - die Anzahl an Knoten gespeicherten
  • links (t) - der linke Unterbaum
  • rechts (t) - der rechte Teilbaum

t1und t2sind isomorph, iff t1und t2leer sind,

oder value (t1) == value (t2)

und

entweder left(t1)isomorph zu left(t2)und right(t1)ist isomorph right(t2),

oder left(t1)isomorph zu right(t2)und right(t1)isomorph zuleft(t2)

Angenommen , die Bäume in einem Array gespeichert sind, so daß das Element 0 die Wurzel und und wenn tein Index eines internen Knotens ist 2t+1und 2t+2sind Indizes ihrer unmittelbaren Kinder, unkomplizierte Umsetzung:

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

Für das zweite Problem, bei jedem Schritt, vergleichen wir den Teilbaum amit der kleineren Wurzel zu dem Teilbaum bmit der kleineren Wurzel und dann dem Teilbaum amit der größeren Wurzel zu dem Teilbaum bmit der größeren Wurzel (kleine und größer als die aktuellen Wurzeln aund 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);
}
Beantwortet am 08/11/2011 um 15:41
quelle vom benutzer

stimmen
0

Für BST:

  1. Nimm die ersten Elemente beider Arrays und Spiel. Wenn nicht gleich dann BST sind nicht gleich.
  2. Finden Sie die erste Straße links Kinder , die nicht gescannt wurde (an den Positionen leftPos1 und leftPos2) und Spiel. Wenn nicht übereinstimmen , dann ist BST nicht gleich.
  3. Finden Sie die erste Straße rechts Kinder , die nicht gescannt wurde (an den Positionen rightPos1 und rightPos2) und Spiel. Wenn nicht übereinstimmen , dann ist BST nicht gleich.
  4. Wenn beide linke und rechte Kinder entsprechen, führen die die gleichen Operationen rekursiv auf dem zwei Paar Sublisten / Teilbaum (von leftPos1 und leftPos2) und (von rightPos1 und rightPos2). Die Mutter dieser Unterstruktur ist das erste Element des Arrays.

Während die linken und rechten Kinder in der Unterliste suchen, kann es Elemente, die bereits gescannt werden. Um solche Elemente herausfinden, stellen Sie sicher, daß das Element, dass es die Kinder des aktuellen Unterbaum sein kann. Wenn der aktuelle Baum, der an der linken Seite des Mutter ist, zu vergleichen, dann das Element mit dem Elternteil, wenn es an der rechten Seite gehören, dann dieses Element ignorieren.

#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;
}
Beantwortet am 16/03/2013 um 18:30
quelle vom benutzer

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