So stellen Sie fest, ob ein Binärbaum in Java ausgeglichen ist

1. Übersicht

Bäume sind eine der wichtigsten Datenstrukturen in der Informatik. Wir sind normalerweise wegen seiner wertvollen Eigenschaften an einem ausgeglichenen Baum interessiert . Ihre Struktur ermöglicht die Ausführung von Operationen wie Abfragen, Einfügungen und Löschungen in logarithmischer Zeit.

In diesem Tutorial erfahren Sie, wie Sie feststellen, ob ein Binärbaum ausgeglichen ist.

2. Definitionen

Lassen Sie uns zunächst einige Definitionen einführen, um sicherzustellen, dass wir uns auf derselben Seite befinden:

  • Ein binärer Baum - eine Art Baum, in dem jeder Knoten null, ein oder zwei untergeordnete Elemente hat
  • Eine Höhe eines Baumes - ein maximaler Abstand von einer Wurzel zu einem Blatt (entspricht der Tiefe des tiefsten Blattes)
  • Ein ausgeglichener Baum - eine Art Baum, bei dem für jeden Teilbaum der maximale Abstand von der Wurzel zu einem Blatt höchstens um eins größer ist als der minimale Abstand von der Wurzel zu einem Blatt

Unten finden Sie ein Beispiel für einen ausgeglichenen Binärbaum. Drei grüne Ränder sind eine einfache Visualisierung zur Bestimmung der Höhe, während die Zahlen die Ebene angeben.

3. Domänenobjekte

Beginnen wir also mit einer Klasse für unseren Baum:

public class Tree { private int value; private Tree left; private Tree right; public Tree(int value, Tree left, Tree right) { this.value = value; this.left = left; this.right = right; } } 

Nehmen wir der Einfachheit halber an, jeder Knoten hat einen ganzzahligen Wert . Beachten Sie, dass wenn der linke und der rechte Baum null sind, unser Knoten ein Blatt ist .

Bevor wir unsere primäre Methode vorstellen, wollen wir sehen, was sie zurückgeben soll:

private class Result { private boolean isBalanced; private int height; private Result(boolean isBalanced, int height) { this.isBalanced = isBalanced; this.height = height; } }

Somit haben wir für jeden einzelnen Anruf Informationen über Höhe und Gleichgewicht.

4. Algorithmus

Mit einer Definition eines ausgeglichenen Baums können wir einen Algorithmus entwickeln. Was wir tun müssen, ist die gewünschte Eigenschaft für jeden Knoten zu überprüfen . Dies kann leicht durch rekursives Durchsuchen der Tiefensuche erreicht werden.

Jetzt wird unsere rekursive Methode für jeden Knoten aufgerufen. Außerdem wird die aktuelle Tiefe verfolgt. Jeder Anruf gibt Informationen über Höhe und Gleichgewicht zurück.

Schauen wir uns nun unsere Tiefenmethode an:

private Result isBalancedRecursive(Tree tree, int depth) { if (tree == null) { return new Result(true, -1); } Result leftSubtreeResult = isBalancedRecursive(tree.left(), depth + 1); Result rightSubtreeResult = isBalancedRecursive(tree.right(), depth + 1); boolean isBalanced = Math.abs(leftSubtreeResult.height - rightSubtreeResult.height) <= 1; boolean subtreesAreBalanced = leftSubtreeResult.isBalanced && rightSubtreeResult.isBalanced; int height = Math.max(leftSubtreeResult.height, rightSubtreeResult.height) + 1; return new Result(isBalanced && subtreesAreBalanced, height); }

Zuerst müssen wir den Fall betrachten, wenn unser Knoten null ist : Wir geben true (was bedeutet, dass der Baum ausgeglichen ist) und -1 als Höhe zurück.

Dann führen wir zwei rekursive Aufrufe für den linken und den rechten Teilbaum durch, um die Tiefe auf dem neuesten Stand zu halten .

Zu diesem Zeitpunkt werden Berechnungen für untergeordnete Elemente eines aktuellen Knotens durchgeführt. Jetzt haben wir alle erforderlichen Daten, um das Gleichgewicht zu überprüfen:

  • Die Variable isBalanced überprüft die Höhe für Kinder und
  • substreesAreBalanced gibt an, ob die Teilbäume auch ausgeglichen sind

Schließlich können wir Informationen über Gleichgewicht und Höhe zurückgeben. Es könnte auch eine gute Idee sein, den ersten rekursiven Aufruf mit einer Fassadenmethode zu vereinfachen:

public boolean isBalanced(Tree tree) { return isBalancedRecursive(tree, -1).isBalanced; }

5. Zusammenfassung

In diesem Artikel haben wir erläutert, wie Sie feststellen können, ob ein Binärbaum ausgeglichen ist. Wir haben einen Ansatz für die Tiefensuche erläutert.

Wie üblich ist der Quellcode mit Tests über GitHub verfügbar.