0Pricing
DSA Interview Prep · Lektion

BST-Einfügen und -Suchen

Implementieren Sie rekursives und iteratives Einfügen und Suchen, verfolgen Sie den Pfad durch den Baum für verschiedene Schlüssel und analysieren Sie die Worst-Case-Komplexität unbalancierter Bäume.

BST-Einfügen und -Suchen ist eine kostenlose DSA Interview Prep-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des DSA Interview Prep-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der DSA Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Die BST-Eigenschaft

Ein Binary Search Tree erfüllt eine Invariante: Für jeden Knoten sind alle Werte in seinem linken Teilbaum strikt kleiner als der Wert des Knotens, und alle Werte in seinem rechten Teilbaum strikt größer. Diese Ordnungseigenschaft, die für den gesamten Teilbaum und nicht nur für die unmittelbaren Kinder gilt, ermöglicht Suchen, Einfügen und Löschen in O(log n) bei ausgeglichenen Bäumen und unterscheidet einen BST von einem allgemeinen Binärbaum.

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

# Valid BST:
#       4
#      / \
#     2   6
#    / \ / \
#   1  3 5  7
# For node 4: left subtree {1,2,3} < 4 < right subtree {5,6,7}
# This holds recursively for EVERY node in the tree.
print('BST property: left < node < right at every level')

Rekursive BST-Suche

Die Suche in einem BST funktioniert wie eine binäre Suche: Vergleichen Sie das Ziel mit dem Wert des aktuellen Knotens und rufen Sie die passende Teilbaumrekursion auf. Wenn das Ziel dem aktuellen Wert entspricht, geben Sie den Knoten zurück. Wenn das Ziel kleiner ist, gehen Sie nach links, bei einem größeren Ziel nach rechts. Geben Sie null zurück, wenn Sie einen leeren Knoten erreichen. Die Laufzeit beträgt O(h) – O(log n) bei ausgeglichenen und O(n) bei schiefen Bäumen.

def search_bst(root, val):
    if not root:
        return None  # not found
    if root.val == val:
        return root  # found
    if val < root.val:
        return search_bst(root.left, val)
    else:
        return search_bst(root.right, val)

root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)

result = search_bst(root, 2)
print(result.val if result else 'Not found')  # 2
result = search_bst(root, 5)
print(result.val if result else 'Not found')  # Not found

Iterative BST-Suche

Die iterative Suche vermeidet den Overhead des Aufrufstapels und wird in produktivem Code bevorzugt. Verwenden Sie einen Zeiger curr, der den Baum durchläuft und je nach Vergleich nach links oder rechts weitergeht. Dies ist eine einfache while-Schleife mit drei Fällen: null (nicht gefunden), Übereinstimmung (gefunden) oder Anpassung der Richtung. Die iterative Suche hat ebenfalls O(h) Laufzeit, benötigt aber O(1) Speicherplatz statt O(h) bei der rekursiven Variante.

def search_bst_iterative(root, val):
    curr = root
    while curr:
        if val == curr.val:
            return curr
        elif val < curr.val:
            curr = curr.left
        else:
            curr = curr.right
    return None  # not found

root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)

node = search_bst_iterative(root, 3)
print(node.val if node else 'Not found')  # 3
print(search_bst_iterative(root, 9))     # None

Rekursives Einfügen in einen BST

Beim Einfügen in einen BST wird die richtige Position ermittelt, indem dieselben Entscheidungen für links oder rechts wie bei der Suche getroffen werden. Anschließend wird an der ersten erreichten Position null ein neuer Knoten eingefügt. Der rekursive Ansatz gibt die möglicherweise neue Wurzel jedes Teilbaums zurück: Wenn der aktuelle Knoten null ist, geben Sie einen neuen TreeNode zurück; andernfalls aktualisieren Sie root.left oder root.right mit dem Ergebnis des rekursiven Aufrufs. Dieses Muster ist übersichtlich und in Interviewlösungen weit verbreitet.

def insert_bst(root, val):
    if not root:
        return TreeNode(val)  # create new node here
    if val < root.val:
        root.left = insert_bst(root.left, val)
    elif val > root.val:
        root.right = insert_bst(root.right, val)
    # val == root.val: duplicate, do nothing (or handle as needed)
    return root

root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root = insert_bst(root, 1)
root = insert_bst(root, 5)
# Tree is now: 4, left=2(left=1), right=7(left=5)
print(root.right.left.val)  # 5

Iteratives Einfügen in einen BST

Beim iterativen Einfügen wird mit einem Zeiger parent der letzte Nicht-Null-Knoten vor der Einfügeposition verfolgt. Durchlaufen Sie den Baum wie bei der Suche und speichern Sie dabei den Elternknoten sowie die zuletzt eingeschlagene Richtung. Wenn Sie null erreichen, hängen Sie den neuen Knoten an der entsprechenden Seite des Elternknotens ein. Behandeln Sie den Sonderfall eines leeren Baums (die Wurzel ist null) immer separat.

def insert_bst_iterative(root, val):
    new_node = TreeNode(val)
    if not root:
        return new_node
    curr = root
    while True:
        if val < curr.val:
            if curr.left is None:
                curr.left = new_node
                break
            curr = curr.left
        else:  # val > curr.val
            if curr.right is None:
                curr.right = new_node
                break
            curr = curr.right
    return root

root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root = insert_bst_iterative(root, 3)
print(root.left.right.val)  # 3

BST im schlimmsten Fall: Schiefe Bäume

Wenn Sie eine sortierte Folge in einen BST einfügen, entsteht ein schiefer Baum, der zu einer verketteten Liste degeneriert. Suche, Einfügen und Löschen haben dann alle eine Laufzeit von O(n). Deshalb gibt es ausgeglichene BSTs (AVL-Bäume, Red-Black-Bäume). Erwähnen Sie in Interviews bei Fragen zur Komplexität eines BST immer diesen Worst Case – die Aussage „durchschnittlich O(log n), im schlechtesten Fall O(n) bei unausgeglichenen Bäumen“ zeigt ein gutes Verständnis.

# Inserting 1, 2, 3, 4, 5 into a BST:
# 1
#  \
#   2
#    \
#     3
#      \
#       4
#        \
#         5
# This is a right-skewed tree: search is O(n) not O(log n)

root = None
for val in [1, 2, 3, 4, 5]:
    root = insert_bst(root, val)

# Verify the skew
node = root
depth = 0
while node:
    depth += 1
    node = node.right
print(f'Height: {depth}')  # 5 = O(n), not O(log n)

Minimum und Maximum finden

In einem BST befindet sich der Minimalwert immer im am weitesten links liegenden Knoten (gehen Sie so lange nach links, bis Sie null erreichen), der Maximalwert entsprechend im am weitesten rechts liegenden Knoten. Diese Operationen mit O(h) Laufzeit werden häufig als Teilroutinen beim Löschen aus einem BST (zum Finden des Inorder-Nachfolgers) und bei Bereichsabfragen verwendet. Wenn Sie diese Hilfsverfahren sicher beherrschen, sparen Sie in Interviews Zeit.

def find_min(root):
    while root.left:
        root = root.left
    return root

def find_max(root):
    while root.right:
        root = root.right
    return root

root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)
root.right.right = TreeNode(9)

print(find_min(root).val)  # 1
print(find_max(root).val)  # 9

Inorder-Nachfolger und -Vorgänger

Der Inorder-Nachfolger eines Knotens ist der Knoten mit dem kleinsten Wert, der größer als der Wert des gegebenen Knotens ist. Wenn der Knoten einen rechten Teilbaum besitzt, ist der Nachfolger find_min(node.right). Wenn er keinen rechten Teilbaum besitzt, ist der Nachfolger der niedrigste Vorfahr, in dessen linkem Teilbaum sich der gegebene Knoten befindet. Dieses Verständnis ist für das Löschen aus einem BST und für BST-Iterator-Probleme entscheidend.

def inorder_successor(root, p):
    successor = None
    while root:
        if p.val < root.val:
            successor = root  # possible successor
            root = root.left
        else:
            root = root.right
    return successor

def inorder_predecessor(root, p):
    predecessor = None
    while root:
        if p.val > root.val:
            predecessor = root  # possible predecessor
            root = root.right
        else:
            root = root.left
    return predecessor

root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(6)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)
p = root.left  # node with val=2
print(inorder_successor(root, p).val)   # 3
print(inorder_predecessor(root, p).val) # 1

Analyse der BST-Suchkomplexität

Die Leistung eines BST hängt vollständig von der Baumhöhe ab. Bei einem ausgeglichenen BST mit n Knoten beträgt die Höhe O(log n), wodurch Suche, Einfügen und Löschen jeweils O(log n) benötigen. Bei einem schiefen BST beträgt die Höhe O(n), sodass alle Operationen O(n) benötigen. Python verfügt im Gegensatz zu Javas TreeMap nicht über einen integrierten ausgeglichenen BST. Sie können daher entweder selbst einen AVL- oder Red-Black-Baum implementieren, sortedcontainers.SortedList verwenden oder für Anwendungsfälle mit Prioritätswarteschlangen auf einen Heap zurückgreifen.

# Python's BST alternatives:
# 1. heapq - min/max heap, O(log n) push/pop
# 2. sortedcontainers.SortedList (third-party, often allowed)
# 3. Manual AVL or Red-Black (rarely required in interviews)

# When interviews say 'use a BST':
# - LeetCode: implement TreeNode-based solution
# - Real interview: mention sortedcontainers or Java TreeMap equivalent
# - O(log n) operations matter when you need ordered access

# For pure insert/lookup without ordering: use dict (O(1) average)
print('Use heap for priority, dict for lookup, BST for ordered range')

Einfügen in einen BST: Sonderfälle

Überprüfen Sie beim Einfügen immer, ob folgende Fälle behandelt werden: leerer Baum (den neuen Knoten als Wurzel zurückgeben), doppelte Werte (festlegen, ob sie ignoriert, links oder rechts eingefügt werden, und diese Entscheidung konsequent umsetzen) sowie sehr große oder kleine Werte. Geben Sie in Interviews vor dem Programmieren an, welche Annahme Sie zu Duplikaten treffen. In LeetCode-Aufgaben gilt üblicherweise, dass alle Werte verschieden sind, sofern nichts anderes angegeben ist.

def insert_bst_no_duplicates(root, val):
    if not root:
        return TreeNode(val)
    if val < root.val:
        root.left = insert_bst_no_duplicates(root.left, val)
    elif val > root.val:
        root.right = insert_bst_no_duplicates(root.right, val)
    # else: val == root.val -> duplicate, skip
    return root

# Test all edge cases:
root = None
root = insert_bst_no_duplicates(root, 5)  # empty tree
root = insert_bst_no_duplicates(root, 5)  # duplicate
root = insert_bst_no_duplicates(root, 3)
root = insert_bst_no_duplicates(root, 7)
print(root.val, root.left.val, root.right.val)  # 5 3 7

BST aus einem sortierten Array

Das Erstellen eines höhenbalancierten BST aus einem sortierten Array (LeetCode #108) verwendet Teile und Herrsche: Das mittlere Element wird zur Wurzel, die linke Hälfte zum linken Teilbaum und die rechte Hälfte zum rechten Teilbaum. Dadurch wird ein ausgeglichener Baum mit der Höhe O(log n) garantiert. Die Laufzeit beträgt O(n), da jedes Element genau einmal verarbeitet wird.

def sorted_array_to_bst(nums):
    if not nums:
        return None
    mid = len(nums) // 2
    root = TreeNode(nums[mid])
    root.left = sorted_array_to_bst(nums[:mid])
    root.right = sorted_array_to_bst(nums[mid+1:])
    return root

nums = [-10, -3, 0, 5, 9]
root = sorted_array_to_bst(nums)
print(root.val)        # 0 (middle element)
print(root.left.val)   # -3
print(root.right.val)  # 9

Kurze Überprüfung

Testen Sie Ihr Verständnis der Konzepte aus Data Structures & Algorithms — Coding Interview Prep aus dieser Lektion.

Zusammenfassung der Lektion

In dieser Lektion haben Sie Folgendes gelernt: die BST-Eigenschaft (linker Teilbaum strikt kleiner, rechter Teilbaum strikt größer), Suche und Einfügen sowohl rekursiv als auch iterativ mit einer Laufzeit von O(h) sowie schiefe Bäume im schlimmsten Fall, bei denen die Höhe n entspricht. Als Nächstes behandeln wir das Löschen aus einem BST und seine drei Fälle.

Häufig gestellte Fragen

Ist die Lektion „BST-Einfügen und -Suchen“ kostenlos?

Ja — der vollständige Text von „BST-Einfügen und -Suchen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des DSA Interview Prep-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der DSA Interview Prep-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „BST-Einfügen und -Suchen“?

Implementieren Sie rekursives und iteratives Einfügen und Suchen, verfolgen Sie den Pfad durch den Baum für verschiedene Schlüssel und analysieren Sie die Worst-Case-Komplexität unbalancierter Bäume. Du übst DSA Interview Prep mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um DSA Interview Prep zu starten?

Keine Vorkenntnisse erforderlich. DSA Interview Prep auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „BST-Einfügen und -Suchen“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser DSA Interview Prep-Lektion Code schreiben und ausführen?

Ja. Jede DSA Interview Prep-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. BST-Einfügen und -Suchen
  2. BST-Löschen: drei Fälle
  3. BST und In-Order-Eigenschaften validieren
  4. K-kleinstes Element, Bereichssumme und BST zu sortiertem Array
← Zurück zu DSA Interview Prep