Zuletzt aktualisiert am 16.12.2025 6 Minuten Lesezeit

Binary Tree

Ein Binary Tree (deutsch: Binärbaum) ist eine fundamentale Datenstruktur in der Informatik, bei der jeder Knoten höchstens zwei Kinder haben kann: ein linkes und ein rechtes Kind. Diese hierarchische Struktur ermöglicht effizientes Suchen, Einfügen und Löschen von Daten und bildet die Grundlage für viele wichtige Algorithmen und Datenstrukturen.

Binärbäume werden in der Praxis für sortierte Datenspeicherung, Suchoperationen, Parser und Prioritätswarteschlangen eingesetzt. Für IT-Azubis sind sie ein zentrales Thema in der Ausbildung und häufiger Prüfungsgegenstand.

Grundlegende Begriffe

Um mit Binärbäumen arbeiten zu können, musst du einige grundlegende Begriffe kennen:

Begriff Beschreibung
Knoten (Node) Element im Baum mit einem Wert und Referenzen auf linkes/rechtes Kind
Wurzel (Root) Oberster Knoten des Baums, Ausgangspunkt für alle Operationen
Blatt (Leaf) Knoten ohne Kinder, befindet sich am Ende eines Pfades
Kante (Edge) Verbindung zwischen zwei Knoten (Parent-Child-Beziehung)
Höhe (Height) Anzahl der Kanten vom Knoten bis zum tiefsten Blatt
Tiefe (Depth) Anzahl der Kanten von der Wurzel bis zum Knoten
Teilbaum (Subtree) Ein Knoten zusammen mit allen seinen Nachkommen

Implementierung eines Knotens

In den meisten Programmiersprachen wird ein Binärbaum-Knoten als Klasse oder Struktur mit einem Wert und zwei Referenzen auf die Kindknoten implementiert:

// Java-Implementierung
class TreeNode {
    int value;
    TreeNode left;
    TreeNode right;

    public TreeNode(int value) {
        this.value = value;
        this.left = null;
        this.right = null;
    }
}
# Python-Implementierung
class TreeNode:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

Arten von Binärbäumen

Es gibt verschiedene spezialisierte Formen von Binärbäumen, die jeweils bestimmte Eigenschaften garantieren:

Voller Binärbaum (Full Binary Tree)

Bei einem vollen Binärbaum hat jeder Knoten entweder genau zwei Kinder oder gar keine Kinder (ist also ein Blatt). Kein Knoten hat nur ein einzelnes Kind.

Vollständiger Binärbaum (Complete Binary Tree)

Ein vollständiger Binärbaum ist auf allen Ebenen vollständig gefüllt, mit Ausnahme möglicherweise der letzten Ebene. Die letzte Ebene wird dabei von links nach rechts aufgefüllt. Diese Struktur wird häufig für Heaps verwendet.

Balancierter Binärbaum (Balanced Binary Tree)

Bei einem balancierten Binärbaum unterscheidet sich die Höhe des linken und rechten Teilbaums jedes Knotens um höchstens 1. Balancierte Bäume garantieren eine logarithmische Höhe und damit effiziente Operationen. Bekannte Beispiele sind AVL-Bäume und Rot-Schwarz-Bäume.

Binärer Suchbaum (Binary Search Tree, BST)

Der binäre Suchbaum ist eine der wichtigsten Varianten. Er folgt einer Ordnungsregel:

  • Alle Werte im linken Teilbaum sind kleiner als der Wert des Knotens
  • Alle Werte im rechten Teilbaum sind größer als der Wert des Knotens
  • Diese Regel gilt rekursiv für jeden Knoten im Baum

Diese Ordnung ermöglicht effizientes Suchen: Bei jedem Vergleich kann die Hälfte der verbleibenden Knoten ausgeschlossen werden, ähnlich wie bei der binären Suche in einem sortierten Array.

Traversierungen (Durchläufe)

Die Traversierung beschreibt, in welcher Reihenfolge die Knoten eines Baums besucht werden. Es gibt drei grundlegende Strategien, die sich in der Reihenfolge von Knoten (N), linkem Teilbaum (L) und rechtem Teilbaum (R) unterscheiden:

Inorder-Traversierung (L - N - R)

Bei der Inorder-Traversierung wird zuerst der linke Teilbaum besucht, dann der aktuelle Knoten, dann der rechte Teilbaum. Wichtig: Bei einem binären Suchbaum liefert die Inorder-Traversierung die Werte in aufsteigend sortierter Reihenfolge.

def inorder(node):
    if node is not None:
        inorder(node.left)      # Linker Teilbaum
        print(node.value)       # Aktueller Knoten
        inorder(node.right)     # Rechter Teilbaum

Preorder-Traversierung (N - L - R)

Die Preorder-Traversierung besucht zuerst den aktuellen Knoten, dann den linken Teilbaum, dann den rechten. Diese Methode eignet sich gut zum Kopieren oder Serialisieren eines Baums, da die Struktur erhalten bleibt.

def preorder(node):
    if node is not None:
        print(node.value)       # Aktueller Knoten
        preorder(node.left)     # Linker Teilbaum
        preorder(node.right)    # Rechter Teilbaum

Postorder-Traversierung (L - R - N)

Bei der Postorder-Traversierung werden erst beide Teilbäume besucht, dann der aktuelle Knoten. Dies ist nützlich, wenn Kindknoten vor dem Elternknoten verarbeitet werden müssen, etwa beim Löschen eines Baums oder beim Auswerten von Ausdrucksbäumen.

def postorder(node):
    if node is not None:
        postorder(node.left)    # Linker Teilbaum
        postorder(node.right)   # Rechter Teilbaum
        print(node.value)       # Aktueller Knoten

Komplexität und Performance

Die Effizienz von Operationen auf Binärbäumen hängt stark von der Struktur des Baums ab:

Operation Balancierter Baum Unbalancierter Baum (Worst Case)
Suchen O(log n) O(n)
Einfügen O(log n) O(n)
Löschen O(log n) O(n)
Traversierung O(n) O(n)

Ein balancierter Baum mit n Knoten hat eine Höhe von etwa log₂(n). Das bedeutet: Bei 1.000 Knoten sind maximal etwa 10 Vergleiche nötig, bei 1.000.000 Knoten nur etwa 20. Ein unbalancierter Baum (z.B. wenn Elemente in sortierter Reihenfolge eingefügt werden) kann zur linearen Kette entarten und verliert damit seinen Performance-Vorteil.

Praxisbeispiel: Einfügen in einen BST

Das Einfügen eines neuen Wertes in einen binären Suchbaum folgt einer einfachen rekursiven Logik:

public TreeNode insert(TreeNode root, int value) {
    // Wenn der Baum leer ist, erstelle neuen Knoten
    if (root == null) {
        return new TreeNode(value);
    }

    // Vergleiche und füge rekursiv ein
    if (value < root.value) {
        root.left = insert(root.left, value);
    } else if (value > root.value) {
        root.right = insert(root.right, value);
    }
    // Bei Gleichheit: Wert bereits vorhanden, nichts tun

    return root;
}

Anwendungsgebiete

Binärbäume sind in vielen Bereichen der Softwareentwicklung unverzichtbar:

  • Sortierte Datenstrukturen: TreeSet und TreeMap in Java, std::set und std::map in C++ basieren auf balancierten Binärbäumen (meist Rot-Schwarz-Bäume)
  • Datenbanken: B-Bäume (eine Verallgemeinerung von Binärbäumen) werden für Indexstrukturen verwendet
  • Prioritätswarteschlangen: Heaps, eine spezielle Form von Binärbäumen, ermöglichen effizientes Einfügen und Entfernen des minimalen/maximalen Elements
  • Compiler und Parser: Ausdrucksbäume (Expression Trees) repräsentieren mathematische und logische Ausdrücke
  • Entscheidungsbäume: Verwendet in Machine Learning und künstlicher Intelligenz
  • Huffman-Codierung: Binärbäume werden für effiziente Datenkompression eingesetzt

Relevanz in der IT-Ausbildung

Binärbäume sind ein zentrales Thema in der Fachinformatiker-Ausbildung für Anwendungsentwicklung. Du solltest verstehen, wie Collections wie TreeSet oder TreeMap intern funktionieren und wann der Einsatz von Baumstrukturen sinnvoll ist.

In IHK-Prüfungen tauchen regelmäßig Aufgaben zu Binärbäumen auf, etwa das Zeichnen eines Baums nach dem Einfügen mehrerer Werte oder das Angeben der Ausgabe einer bestimmten Traversierung. Das Verständnis von Baumstrukturen hilft dir auch dabei, die Komplexität von Algorithmen besser einzuschätzen.

Quellen und weiterführende Links