Finden tauschte Knoten in einem BST

stimmen
6

Ich versuche, ein Programm zu schreiben, und drucken zwei Knoten in BST erkennen kann, die ausgelagert wurden.

In einem dreistufigen Baum erreichte ich in der Nähe der Lösung dieses Ansatzes.

If (!AllSubTreeAreValid())
{
//Nodes swapped on same side of main root node
}
else
{
  int max = getMax(root->left);
  int min = getMin(root->right);
  if(max > root->data || min < root->data )
  {
     //Nodes swapped on different sides of main root node
     //Print max and min values

  }
else 
{
 //No node swappped
}
}

//Helper functions
int GetMaxEle(TreeNode* tree)
{
    while(tree->right!=NULL)
    {
        tree=tree->right;
    }
    return tree->info;
}

int GetMinEle(TreeNode* tree)
{
    while(tree->left!=NULL)
    {
        tree=tree->left;
    }
    return tree->info;
}

aber der obige Ansatz scheiterte, als ich versuchte, mit vier Leveln Baum zu testen.

             20

      15            30

   10    17       25     33

9  16  12  18  22  26  31  34

Als in der rechten Unterbaum des Wurzelknoten 15, 12 ist immer noch höher (Verletzung).

Wobei in der linken Teilbaum-Wurzelknoten 15, 16 ist immer noch höher (Verletzung).

So, 16, 12 sind die ausgetauschten Elemente in der obigen BST. Wie kann ich sie durch das Programm finden?

Veröffentlicht am 31/08/2011 um 17:30
quelle vom benutzer
In anderen Sprachen...                            


3 antworten

stimmen
0

Ich denke, Ihr getMin et getMax abgesprochen Hypothesen arbeitet, die der Baum ein BST ist, so

T getMax(tree) {
  return tree -> right == null 
    ? tree -> value 
    : getMax(tree -> right);
}

(Oder der entsprechende Code mit einer Schleife). Wenn ja, prüft den Code höchstens drei Werte im Baum. Selbst wenn getMax und getMin den vollständigen Baum den tatsächlichen max / min erhalten durchlaufen, würden Sie noch stützen Ihren Test auf nur zwei Vergleichen. Wenn Sie überprüfen möchten, dass Ihr Baum die BST Eigenschaft erfüllen, ist es offensichtlich, dass Sie alle Werte zu prüfen haben. Sein genug jeden Knoten mit seinen Eltern zu vergleichen.

void CheckIsBst(Tree *tree) {
  if (tree -> left != null) {
    if (tree -> left -> value > tree -> value) {
      // print violation
    }
    CheckIsBst(tree -> left);   
  }
  // same with -> right, reversing < to > in the test
}

Bearbeiten : das falsch war, siehe Kommentar. Ich glaube , das man in Ordnung ist.

void checkIsBst(Tree *Tree, Tree *lowerBound, Tree *upperBound) {
  if(lowerBound!= null && lowerBound -> value > tree -> Value) {
    //violation
  }
  // same for upper bound, check with <
  if (tree -> left != null) {
    if (tree -> left -> value > tree -> value) {
      // print violation
     }
     CheckIsBst(tree -> left, lowerBound, tree);   
  }
  // same for right, reversing comparison 
  // setting lowerBound to tree instead of upperBound
}

Aufruf von der Wurzel mit Null-Grenzen

Beantwortet am 31/08/2011 um 18:03
quelle vom benutzer

stimmen
8

Eine Möglichkeit, dieses Problem zu denken, ist die Tatsache zu nutzen, dass ein Inorder Fuß des Baumes wird alle Elemente in sortierter Reihenfolge erzeugen. Wenn Sie Abweichungen von der sortierten Reihenfolge während dieser Wanderung erkennen können, können Sie versuchen, die beiden Elemente zu finden, die an der falschen Stelle sind.

Mal sehen, wie das erste für eine einfache sortiertes Array zu tun, dann ist unser Algorithmus verwenden, um etwas zu bauen, die auf Bäumen funktioniert. Intuitiv, wenn wir mit einem sortierten Array beginnen und dann tauschen zwei (nicht-gleich!) Elemente, werden wir mit einem gewissen Anzahl von Elementen in der Anordnung am Ende fehl am Platz zu sein. Zum Beispiel gegeben, um die Array

1 2 3 4 5

Wenn wir 2 und 4 tauschen, enden wir mit dieser Anordnung auf:

1 4 3 2 5

Wie würden wir feststellen, dass 2 und 4 hier vertauscht wurden? Nun, da 4 der größere der beiden Elemente und wurde nach unten getauscht, sollte es größer sein als beide Elemente um ihn herum. In ähnlicher Weise wurde wegen 2 vertauscht, sollten sie kleiner sein, als beide Elemente um ihn herum. Daraus könnte man schließen, dass 2 und 4 vertauscht wurden.

Allerdings ist dies nicht immer korrekt funktionieren. Angenommen, dass wir tauschen 1 und 4:

4 2 3 1 5

Hier ist sowohl 2 und 1 sind kleiner als ihre benachbarten Elemente, und beide 4 und 3 sind größer als ihre. Daraus können wir sagen, dass zwei dieser vier irgendwie vertauscht wurden, aber es ist nicht klar, welche davon sollten wir vertauschen. Wenn wir jedoch die größte und die kleinste dieser Werte (1 bzw. 4) nehmen wir am Ende das Paar erhalten, die ausgelagert wurde.

Allgemeiner gesagt, die Elemente zu finden, die in der Reihenfolge vertauscht wurden, wollen Sie finden

  • Das größte lokale Maximum in der Anordnung.
  • Das kleinste lokale Minimum in der Anordnung.

Diese beiden Elemente sind fehl am Platz und sollte ausgetauscht werden.

Nun lassen Sie uns darüber nachdenken, wie diese auf Bäume anzuwenden. Da ein Inorder Fuß des Baumes wird die sortierte Folge mit den beiden Elementen aus der Ordnung zu erzeugen, würde eine Möglichkeit sein, den Baum zu gehen, die Aufzeichnung die Inorder Folge von Elementen, die wir gefunden haben, dann den obigen Algorithmus. Betrachten Sie zum Beispiel Ihre ursprüngliche BST:

              20
         /         \
      15             30
     /   \         /   \ 
   10    17      25     33
  / |   /  \    /  \    |  \
9  16  12  18  22  26  31  34

Wenn wir dies in ein Array linearisieren, erhalten wir

9 10 16 15 12 17 18 20 22 25 26 30 31 33 34

Beachten Sie, dass 16 größer ist als ihre umgebenden Elemente und 12 geringer als sein. Dies sagt uns sofort, dass 12 und 16 vertauscht wurden.

Ein einfacher Algorithmus zur Lösung dieses Problems, wäre daher einen Inorder Spaziergang des Baumes zu tun , es in eine Sequenz wie ein linearisieren vectoroder deque, dann diese Sequenz zu scannen , das größte lokale Maximum und das kleinste lokale Minimum zu finden. Dies würde in O (n) Zeit ausgeführt, O (n) Raum verwendet wird . Ein heikler , aber mehr Platz sparender Algorithmus wäre nur bei einer Zeitspur von drei Knoten zu halten - den aktuellen Knoten, seinen Vorgänger und seinen Nachfolger - die die Speichernutzung zu O (1) reduziert.

Hoffe das hilft!

Beantwortet am 31/08/2011 um 21:22
quelle vom benutzer

stimmen
0

der Baum - Traversal durch getan templatetypedef funktioniert , wenn Sie sicher sind , gibt es nur eine Swap ist. Ansonsten schlage ich vor, eine Lösung auf Ihrem ursprünglichen Code basiert:

int GetMax(TreeNode* tree) {
    int max_right, max_left, ret;

    ret = tree->data;
    if (tree->left != NULL) {
        max_left = GetMax(tree->left);
        if (max_left > ret)
            ret = max_left;
    }
    if (tree->right != NULL) {
        max_right = GetMax(tree->right);
        if (max_right > ret)
            ret = max_right;
    }

    return ret;
}

int GetMin(TreeNode* tree) {
    int min_right, min_left, ret;

    ret = tree->data;
    if (tree->left != NULL) {
        min_left = GetMin(tree->left);
        if (min_left < ret)
            ret = min_left;
    }
    if (tree->right != NULL) {
        min_right = GetMin(tree->right);
        if (min_right < ret)
            ret = min_right;
    }

    return ret;
}

void print_violations(TreeNode* tree) {
    if ((tree->left != NULL) && (tree->right != NULL)) {
        int max_left = GetMax(tree->left);
        int min_right = GetMin(tree->right);
        if (max_left > tree->data && min_right < tree->data) {
            printf("Need to swap %d with %d\n", max_left, min_right);
        }
    }
    if (tree->left != NULL)
        print_violations(tree->left);
    if (tree->right != NULL)
        print_violations(tree->right);
}

Es ist langsamer, aber er druckt alle Swaps es identifiziert. Änderbar alle Verletzungen (zB if (max_left> tree-> Daten) Druckverletzung) zu drucken. Sie können die Leistung verbessern, wenn Sie zwei Felder in die TreeNode mit den maximalen und minimalen für diesen Teilbaum vorberechnet hinzufügen können.

Beantwortet am 01/09/2011 um 08:43
quelle vom benutzer

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