/
/
·
·
/
/
·
·
  • Einführung
  • Das Problem
  • Die Definition
  • Vier Arten von Graphen
  • Wie wird ein Graph gespeichert?
  • BFS, Breadth-First Search (Ebenenweise)
  • DFS, Depth-First Search (in die Tiefe)
  • BFS vs. DFS, wann was?
  • Kürzester Pfad: Dijkstra (Bonus)
  • Wichtige Eigenschaften
  • Klausur-Tricks
  • Wo brauchst du Graphen?
ThemenAlgorithmenGraphen
Algorithmen·3Lerneinheiten·28min·Stand02.08.2026

Graphen.

Ein Graph ist eine Menge von Knoten, die durch Kanten verbunden sind. Formal: G=(V,E)G = (V, E)G=(V,E) mit VVV als Knotenmenge und EEE als Kantenmenge. Praktisch modellierst du damit alles, was Beziehungen hat: Straßennetz, soziale Netzwerke, Web-Links, Abhängigkeiten zwischen Vorlesungen. Du lernst hier den Unterschied zwischen gerichtet vs ungerichtet, gewichtet vs ungewichtet, die zwei Standard-Repräsentationen Adjazenzmatrix (O(V2)O(V^2)O(V2) Speicher) vs Adjazenzliste (O(V+E)O(V+E)O(V+E) Speicher), die zwei wichtigsten Traversierungs-Algorithmen BFS (Queue-basiert, kürzeste Pfade in ungewichteten Graphen) und DFS (Stack/Rekursion-basiert, topologische Sortierung in DAGs), den Dijkstra-Algorithmus für kürzeste Pfade in gewichteten Graphen (nur bei nicht-negativen Kanten; bei negativen Kanten Bellman-Ford verwenden) und die Euler-/Hamilton-Pfad-Charakterisierungen.

Die zentralen Konzepte für die Klausur:

  • Gerichtet vs ungerichtet: hat eine Kante eine Richtung (z.B. Twitter-Follow) oder nicht (z.B. Facebook-Freundschaft)
  • Gewichtet vs ungewichtet: haben Kanten Werte (z.B. Entfernung in km) oder nicht
  • Adjazenzmatrix vs Adjazenzliste: Matrix braucht O(V²) Speicher, Liste nur O(V+E), dafür ist Lookup teurer
  • BFS (Breitensuche) mit Queue: liefert kürzeste Pfade in ungewichteten Graphen
  • DFS (Tiefensuche) mit Stack/Rekursion: gut für Zyklen-Erkennung und topologische Sortierung
  • Dijkstra: kürzester Weg in gewichteten Graphen mit nicht-negativen Kanten

In Klausuren wirst du oft gefragt: gegeben ein Graph, traversiere ihn mit BFS oder DFS und gib die Reihenfolge der besuchten Knoten an. Lerne den Pseudocode, nicht nur die Idee.

  • Google Maps: kürzester Weg von Berlin nach München?
  • Facebook: zeig mir Freunde von Freunden
  • Web: alle Seiten erreichbar von startseite.de
  • Stundenplan: kann ich Vorlesung A, B, C zeitlich kombinieren?

Alles Graph-Probleme. Kein anderes Datenstruktur-Konzept hat so viele Anwendungen.

Ein Graph G=(V,E)G = (V, E)G=(V,E) besteht aus einer Menge Knoten VVV (vertices) und einer Menge Kanten EEE (edges) zwischen diesen Knoten.

       A ─── B ─── C
       │     │     │
       D ─── E ─── F
             │   ╱
             G ─╱

V = {A, B, C, D, E, F, G} E = {AB, AD, BC, BE, CF, DE, EF, EG, FG}

VarianteBeschreibungBeispiel
UngerichtetKanten ohne RichtungFacebook-Freundschaft
GerichtetKanten haben Pfeil →Twitter-Follower
GewichtetKanten haben WertStraßennetz mit km
Ungewichtetalle Kanten gleichWeb-Verlinkungen

Klausur-Klassiker: zuerst klären, was für ein Graph vorliegt. Algorithmen reagieren unterschiedlich.

Zwei Standard-Repräsentationen:

Adjacency Matrix

Eine n×nn \times nn×n-Matrix mit 0/1 (oder Gewichten):

    A  B  C  D  E  F  G
 A [0  1  0  1  0  0  0]
 B [1  0  1  0  1  0  0]
 C [0  1  0  0  0  1  0]
 D [1  0  0  0  1  0  0]
 E [0  1  0  1  0  1  1]
 F [0  0  1  0  1  0  1]
 G [0  0  0  0  1  1  0]
  • ✅ O(1) Existenz-Check "ist Kante AB drin?"
  • ✅ Bei dichten Graphen oft sinnvoll, weil EEE nahe V2V^2V2 liegt und O(1)-Kantenchecks möglich sind
  • ❌ O(V2V^2V2) Speicher, auch wenn nur wenige Kanten gesetzt sind
  • ❌ Iterieren über Nachbarn: O(VVV)

Adjacency List

Pro Knoten eine Liste der Nachbarn:

A → [B, D]
B → [A, C, E]
C → [B, F]
D → [A, E]
E → [B, D, F, G]
F → [C, E, G]
G → [E, F]
  • ✅ O(V + E) Speicher, sparsam bei wenigen Kanten
  • ✅ Iterieren über Nachbarn: O(grad(v))
  • ❌ Existenz-Check langsamer: O(grad(v))

Bei ungerichteten Graphen wird jede Kante in der Standard-Adjazenzlisten-Implementierung zweimal gespeichert (einmal in jeder Endpunkt-Liste), damit Nachbar-Iteration von beiden Enden funktioniert. Asymptotisch bleibt der Speicher O(V+E)O(V+E)O(V+E).

Faustregel: bei sparsen Graphen (E≪V2E \ll V^2E≪V2) Adjacency List, bei dichten Adjacency Matrix.

Matrix vs Liste: Vergleich auf einen Blick

KriteriumAdjazenzmatrixAdjazenzliste
SpeicherO(V2)O(V^2)O(V2)O(V+E)O(V + E)O(V+E)
Existenz-Check Kante (u,v)O(1)O(1)O(1)O(deg⁡(u))O(\deg(u))O(deg(u))
Iteration über Nachbarn von vvvO(V)O(V)O(V)O(deg⁡(v))O(\deg(v))O(deg(v))
Kante einfügenO(1)O(1)O(1)O(1)O(1)O(1) amortisiert
Kante löschenO(1)O(1)O(1)O(deg⁡(u))O(\deg(u))O(deg(u))
BFS/DFS gesamtO(V2)O(V^2)O(V2)O(V+E)O(V + E)O(V+E)
Wann wählendichte Graphen (E≈V2E \approx V^2E≈V2) oder häufige Existenz-Checkssparse Graphen (E≪V2E \ll V^2E≪V2) oder Nachbar-Iteration dominiert

Geht schichtweise durch den Graph: erst alle direkten Nachbarn, dann deren Nachbarn, usw.

function BFS(start):
    visited = {start}
    queue = [start]
    while queue not empty:
        node = queue.pop_front()        // Queue: FIFO
        print(node)
        for neighbor in adjacency[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.push_back(neighbor)

Datenstruktur: Queue (FIFO).

Beispiel auf dem Graph oben, Start A:

Schritt 1: Queue [A] → besuche A → Nachbarn B, D dazu
Schritt 2: Queue [B, D] → besuche B → Nachbarn C, E dazu
Schritt 3: Queue [D, C, E] → besuche D
Schritt 4: Queue [C, E] → besuche C → Nachbar F dazu
Schritt 5: Queue [E, F] → besuche E → Nachbar G dazu
Schritt 6: Queue [F, G] → besuche F
Schritt 7: Queue [G] → besuche G

Reihenfolge: A, B, D, C, E, F, G

Pfad-Eigenschaft: BFS findet kürzeste Wege nach Anzahl der Kanten in ungewichteten Graphen, sofern der Zielknoten erreichbar ist.

Komplexität (Adjazenzliste): O(V+E)O(V + E)O(V+E), jeder Knoten wird einmal besucht, jede Kante höchstens konstant oft betrachtet (bei ungerichteten Graphen einmal pro Endpunkt). Mit Adjazenzmatrix wird BFS/DFS typischerweise O(V2)O(V^2)O(V2), weil pro Knoten alle möglichen Nachbarn geprüft werden.

Geht so tief wie möglich, dann zurück.

function DFS(start):
    visited = {start}
    stack = [start]
    while stack not empty:
        node = stack.pop()              // Stack: LIFO
        print(node)
        for neighbor in adjacency[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                stack.push(neighbor)

Oder rekursiv (eleganter):

function DFS(node, visited):
    if node in visited: return
    visited.add(node)
    print(node)
    for neighbor in adjacency[node]:
        DFS(neighbor, visited)

Datenstruktur: Stack (LIFO) oder Rekursion (System-Stack).

Beispiel Graph oben, Start A (Nachbarn alphabetisch besucht):

Stack [A] → besuche A, push D, B (umgekehrt!) → Stack [D, B]
Stack [D, B] → pop B → besuche B, push E, C → Stack [D, E, C]
Stack [D, E, C] → pop C → besuche C, push F → Stack [D, E, F]
... → A, B, C, F, E, D, G

Achtung Reihenfolge: damit beim iterativen Stack-DFS die Nachbarn alphabetisch besucht werden, müssen sie in umgekehrter Reihenfolge gepusht werden, der zuletzt gepushte wird zuerst gepoppt.

Pfad-Eigenschaft: DFS ist NICHT für kürzeste Pfade. Aber super für: Zyklen finden, topologisches Sortieren, Zusammenhangskomponenten.

Komplexität (Adjazenzliste): O(V+E)O(V + E)O(V+E), wie BFS. Mit Adjazenzmatrix: O(V2)O(V^2)O(V2).

FrageBFSDFS
DatenstrukturQueue (FIFO)Stack (LIFO) / Rekursion
ReihenfolgeEbenenweiseIn die Tiefe
Kürzester Pfad?Ja (ungewichtet, nach Kanten)Nein
Zyklus finden?MöglichKlassisch
Topologische Sortierung?Per Kahn-Algorithmus mit QueueJa (DFS-Klassiker)
Speicher (allgemeiner Graph)O(V) (visited + Queue)O(V) (visited + Stack/Rekursion)
Speicher (Suchbaum, b/d-Notation)O(b · d) breitO(d) tief
ImplementierungIterativRekursiv oder iterativ

Faustregel: "kürzester Pfad" → BFS. "alle Pfade", "Zyklus", "Sortierung" → DFS.

Bei gewichteten Graphen reicht BFS nicht. Dijkstra löst das.

function Dijkstra(start, target):
    dist[start] = 0; dist[other] = ∞
    pq = priority_queue([(0, start)])     // Min-Heap nach Distanz
    while pq not empty:
        (d, node) = pq.pop_min()
        if d > dist[node]: continue       // veralteter PQ-Eintrag, überspringen
        if node == target: return d
        for (neighbor, weight) in adjacency[node]:
            new_dist = d + weight
            if new_dist < dist[neighbor]:
                dist[neighbor] = new_dist
                pq.push((new_dist, neighbor))

Der if d > dist[node] Check filtert veraltete PQ-Einträge, wenn ein Knoten schon mit einer besseren Distanz expandiert wurde, übersprungen wir den alten Eintrag. Ohne diesen Check wird derselbe Knoten möglicherweise mehrfach aus der PQ gepoppt (wenn mehrere Distanz-Updates in der PQ landen), was die Laufzeit verschlechtert, aber die Korrektheit bei nicht-negativen Gewichten nicht verletzt.

Dijkstra braucht eine Priority Queue (Min-Heap) als Datenstruktur. Komplexität: O((V + E) log V).

Achtung: Dijkstra funktioniert NUR mit nicht-negativen Gewichten. Bei negativen Kanten → Bellman-Ford.

Zusammenhängend:

  • Ungerichtet: jeder Knoten kann jeden anderen erreichen. (Bei BFS/DFS von einem Start: wenn am Ende alle Knoten besucht sind, ist der Graph zusammenhängend.)
  • Gerichtet: man unterscheidet stark zusammenhängend (jeder erreicht jeden über gerichtete Wege) und schwach zusammenhängend (der zugrunde liegende ungerichtete Graph ist zusammenhängend).

Zyklus: ein geschlossener Pfad, der zum Start zurückkehrt, typischerweise mit mindestens einer Kante, ohne zwischendurch Knoten zu wiederholen. In gerichteten Graphen müssen alle Kantenrichtungen eingehalten werden. DFS erkennt Zyklen, wenn ein bereits besuchter Knoten im aktuellen Pfad erreicht wird.

Baum (für ungerichtete Graphen): zusammenhängend und azyklisch. Mit nnn Knoten genau n−1n-1n−1 Kanten. (Für gerichtete Bäume / Arboreszenzen gelten andere Definitionen.)

Bipartit: Knoten lassen sich in zwei Mengen teilen, Kanten gehen nur zwischen den Mengen. BFS findet das mit 2-Färbung.

Grad eines Knotens: Anzahl Kanten, die ihn berühren. Bei gerichteten Graphen: Eingangsgrad und Ausgangsgrad.

Trick 1, Datenstruktur immer angeben: BFS = Queue, DFS = Stack/Rekursion. In Klausur immer dazu sagen.

Trick 2, Reihenfolge bei DFS ist nicht eindeutig. Wenn die Aufgabe DFS verlangt, gib die Nachbar-Reihenfolge an (üblich: alphabetisch oder ID-aufsteigend).

Trick 3, Visited-Set vergessen = Endlosschleife. Beim Erkunden eines Graphen IMMER markieren, welche Knoten schon besucht wurden.

Trick 4, Komplexität BFS / DFS hängt von der Repräsentation ab:

  • Adjazenzliste: O(V+E)O(V + E)O(V+E), Klausur-Standard.
  • Adjazenzmatrix: O(V2)O(V^2)O(V2), pro Knoten alle möglichen Nachbarn prüfen.

Trick 5, Adjacency-Matrix vs. Liste:

  • Matrix: gut bei dichten Graphen oder häufigen "ist Kante drin?"-Checks. Speicher O(V²).
  • Liste: gut bei sparsen Graphen. Speicher O(V + E).

Trick 6, Wege zählen: Anzahl der Kanten in einem Pfad. Bei BFS: Anzahl der Ebenen vom Start.

Trick 7, Zyklus-Erkennung:

  • Ungerichtet: DFS, achten auf Kanten zu schon besuchten Knoten (außer Parent).
  • Gerichtet: DFS mit drei Farben (weiß/grau/schwarz).

Trick 8, Kanten-Anzahl:

  • Ungerichteter Graph mit n Knoten: max. (n2)=n(n−1)2\binom{n}{2} = \frac{n(n-1)}{2}(2n​)=2n(n−1)​ Kanten.
  • Vollständig (alle mit allen) → "K_n".

Trick 9, Eulerweg / Eulerkreis (jede Kante genau einmal, ungerichtet):

  • Eulerweg: existiert, wenn genau 0 oder genau 2 Knoten ungeraden Grades haben, und der Graph (ohne isolierte Knoten) zusammenhängend ist.
  • Eulerkreis: braucht genau 0 Knoten ungeraden Grades, und der Graph (ohne isolierte Knoten) zusammenhängend ist.

Trick 10, Hamiltonkreis: jeden Knoten genau einmal, NP-schwer, in der Klausur Vorsicht: kein Polynom-Algorithmus bekannt.

Trick 11, Dijkstra-Voraussetzung: Dijkstra nur bei nicht-negativen Kantengewichten. Bei negativen Kanten Bellman-Ford verwenden (oder bei negativen Zyklen die Unmöglichkeit feststellen). Wird in MC-Klausuren gerne als Fallstrick eingebaut.

  • Maps & Routenplanung: Dijkstra, A*-Algorithmus
  • Soziale Netzwerke: Freundschafts-Graph, "Freunde von Freunden" via BFS
  • Web-Crawler: Web ist ein gerichteter Graph, Crawler benutzt BFS oder DFS
  • Compiler: Abhängigkeits-Graph zwischen Modulen, topologische Sortierung
  • AI / Pathfinding: Routensuche per Dijkstra / A*. Spiele-KI nutzt zusätzlich Spielbäume (Game Trees), eine spezielle Baumstruktur, kein allgemeiner Graph.
  • Datenbank-Joins: Query-Pläne sind Graphen
  • VLSI-Design / Circuit-Layout: physische Layouts modelliert als Graphen
  • Bioinformatik: Protein-Interaktions-Netzwerke
  • Empfehlungssysteme: User-Item-Bipartite-Graph

Faustregel: wenn die Aufgabe "Verbindungen", "Wege", "Erreichbarkeit", "Reihenfolge mit Abhängigkeiten" beinhaltet, wahrscheinlich Graph.

Klick einen Knoten als Start, wähle BFS oder DFS, dann Play. Beobachte:

  • Aktueller Knoten in Vermillion (gerade besucht)
  • Bereits besucht in heller Tönung mit accent-Border
  • Frontier (Queue/Stack-Inhalt) als Boxen unten links
  • Reihenfolge der Besuche unten rechts (1., 2., 3., …)

Probier folgendes:

  • Start A, BFS → ebenenweise: A, B, D, C, E, F, G
  • Start A, DFS → in die Tiefe: A, B, C, F, E, D, G (Reihenfolge anders!)
  • Start G, BFS → wie viele Schritte bis A erreicht ist? (Antwort: 4)
  • Step-Button: einen Schritt manuell machen, statt Auto-Play
  • Speed-Toggle 1×/2×/5× für die Animation

Sieh dir den Unterschied zwischen Queue (BFS, FIFO) und Stack (DFS, LIFO) live an, das ist der Kern der beiden Algorithmen.

Lade Visualisierung...

Faustregel zum Mitnehmen: BFS = ebenenweise (Queue, kürzester Pfad). DFS = in die Tiefe (Stack/Rekursion, Zyklen). Beide laufen in O(V + E), der Unterschied ist die Datenstruktur.


BFS in Reinform: eine Queue für die Reihenfolge, ein visited-Set gegen Doppelbesuche. Wir starten auf einem kleinen 6-Knoten-Baum (A oben, B/C zweite Ebene, D/E/F dritte Ebene) und schauen wie sich Queue und visited Schritt für Schritt füllen. Klausur-Klassiker: was kommt zuerst aus der Queue?

Lade Visualisierung...

Anmelden, um den Fortschritt zu speichern.

Nächster Schritt

Wenn du fertig bist: jetzt üben.

Aktives Abrufen festigt Wissen schneller als nochmal lesen.

War das hilfreich?

Verwandte Themen

  • Big-O Notation
  • Bubblesort
  • Mergesort
  • Quicksort
  • Sortier-Vergleich

Folgt

  • Minimale Spannbäume (Prim, Kruskal)
  • Dijkstra-Algorithmus

Tools

Bald: Karteikarten · Spaced-Repetition · Mind-Map-Export

Fachliche Qualität
S-Tier · GoldstandardZuletzt geprüft am 18.05.2026

Diese Lerneinheit wurde für typische Bachelor-Klausuren konzipiert. So prüfen wir · Fehler entdeckt? Melde ihn uns oder markiere die fragliche Stelle direkt im Text oben.

Klausur-ÜbersichtKomplette Übersicht: alle Tabs als linearer Text zum Lernen
▾

Alle Tabs der Lerneinheit (Erklärung · Interaktiv · Quiz) als durchgehender Text. Ideal zum Wiederholen vor der Klausur, und für Suchmaschinen wie Google, Bing und KI-Suche (ChatGPT, Perplexity).

Inhalt dieser Übersicht

  1. Erklärung(Erklärung)
  2. Interaktiv(Visualisierung / Interaktiv)
  3. Quiz(Quiz / Klausurfragen)
Teil 1·Erklärung

Erklärung

Ein Graph ist eine Menge von Knoten, die durch Kanten verbunden sind. Formal: G = (V, E) mit V als Knotenmenge und E als Kantenmenge. Praktisch modellierst du damit alles, was Beziehungen hat: Straßennetz, soziale Netzwerke, Web-Links, Abhängigkeiten zwischen Vorlesungen. Du lernst hier den Unterschied zwischen gerichtet vs ungerichtet, gewichtet vs ungewichtet, die zwei Standard-Repräsentationen Adjazenzmatrix (O(V²) Speicher) vs Adjazenzliste (O(V+E) Speicher), die zwei wichtigsten Traversierungs-Algorithmen BFS (Queue-basiert, kürzeste Pfade in ungewichteten Graphen) und DFS (Stack/Rekursion-basiert, topologische Sortierung in DAGs), den Dijkstra-Algorithmus für kürzeste Pfade in gewichteten Graphen (nur bei nicht-negativen Kanten; bei negativen Kanten Bellman-Ford verwenden) und die Euler-/Hamilton-Pfad-Charakterisierungen.

Die zentralen Konzepte für die Klausur:

  • Gerichtet vs ungerichtet: hat eine Kante eine Richtung (z.B. Twitter-Follow) oder nicht (z.B. Facebook-Freundschaft)
  • Gewichtet vs ungewichtet: haben Kanten Werte (z.B. Entfernung in km) oder nicht
  • Adjazenzmatrix vs Adjazenzliste: Matrix braucht O(V²) Speicher, Liste nur O(V+E), dafür ist Lookup teurer
  • BFS (Breitensuche) mit Queue: liefert kürzeste Pfade in ungewichteten Graphen
  • DFS (Tiefensuche) mit Stack/Rekursion: gut für Zyklen-Erkennung und topologische Sortierung
  • Dijkstra: kürzester Weg in gewichteten Graphen mit nicht-negativen Kanten

In Klausuren wirst du oft gefragt: gegeben ein Graph, traversiere ihn mit BFS oder DFS und gib die Reihenfolge der besuchten Knoten an. Lerne den Pseudocode, nicht nur die Idee.

Das Problem

  • Google Maps: kürzester Weg von Berlin nach München?
  • Facebook: zeig mir Freunde von Freunden
  • Web: alle Seiten erreichbar von startseite.de
  • Stundenplan: kann ich Vorlesung A, B, C zeitlich kombinieren?

Alles Graph-Probleme. Kein anderes Datenstruktur-Konzept hat so viele Anwendungen.

Die Definition

Ein Graph G = (V, E) besteht aus einer Menge Knoten V (vertices) und einer Menge Kanten E (edges) zwischen diesen Knoten.

       A ─── B ─── C
       │     │     │
       D ─── E ─── F
             │   ╱
             G ─╱

V = {A, B, C, D, E, F, G} E = {AB, AD, BC, BE, CF, DE, EF, EG, FG}

Vier Arten von Graphen

VarianteBeschreibungBeispiel
UngerichtetKanten ohne RichtungFacebook-Freundschaft
GerichtetKanten haben Pfeil →Twitter-Follower
GewichtetKanten haben WertStraßennetz mit km
Ungewichtetalle Kanten gleichWeb-Verlinkungen

Klausur-Klassiker: zuerst klären, was für ein Graph vorliegt. Algorithmen reagieren unterschiedlich.

Wie wird ein Graph gespeichert?

Zwei Standard-Repräsentationen:

Adjacency Matrix

Eine n × n-Matrix mit 0/1 (oder Gewichten):

    A  B  C  D  E  F  G
 A [0  1  0  1  0  0  0]
 B [1  0  1  0  1  0  0]
 C [0  1  0  0  0  1  0]
 D [1  0  0  0  1  0  0]
 E [0  1  0  1  0  1  1]
 F [0  0  1  0  1  0  1]
 G [0  0  0  0  1  1  0]
  • ✅ O(1) Existenz-Check "ist Kante AB drin?"
  • ✅ Bei dichten Graphen oft sinnvoll, weil E nahe V² liegt und O(1)-Kantenchecks möglich sind
  • ❌ O(V²) Speicher, auch wenn nur wenige Kanten gesetzt sind
  • ❌ Iterieren über Nachbarn: O(V)
Adjacency List

Pro Knoten eine Liste der Nachbarn:

A → [B, D]
B → [A, C, E]
C → [B, F]
D → [A, E]
E → [B, D, F, G]
F → [C, E, G]
G → [E, F]
  • ✅ O(V + E) Speicher, sparsam bei wenigen Kanten
  • ✅ Iterieren über Nachbarn: O(grad(v))
  • ❌ Existenz-Check langsamer: O(grad(v))

Bei ungerichteten Graphen wird jede Kante in der Standard-Adjazenzlisten-Implementierung zweimal gespeichert (einmal in jeder Endpunkt-Liste), damit Nachbar-Iteration von beiden Enden funktioniert. Asymptotisch bleibt der Speicher O(V+E).

Faustregel: bei sparsen Graphen (E ll V²) Adjacency List, bei dichten Adjacency Matrix.

Matrix vs Liste: Vergleich auf einen Blick
KriteriumAdjazenzmatrixAdjazenzliste
SpeicherO(V²)O(V + E)
Existenz-Check Kante (u,v)O(1)O(deg(u))
Iteration über Nachbarn von vO(V)O(deg(v))
Kante einfügenO(1)O(1) amortisiert
Kante löschenO(1)O(deg(u))
BFS/DFS gesamtO(V²)O(V + E)
Wann wählendichte Graphen (E ≈ V²) oder häufige Existenz-Checkssparse Graphen (E ll V²) oder Nachbar-Iteration dominiert

BFS, Breadth-First Search (Ebenenweise)

Geht schichtweise durch den Graph: erst alle direkten Nachbarn, dann deren Nachbarn, usw.

function BFS(start):
    visited = {start}
    queue = [start]
    while queue not empty:
        node = queue.pop_front()        // Queue: FIFO
        print(node)
        for neighbor in adjacency[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.push_back(neighbor)

Datenstruktur: Queue (FIFO).

Beispiel auf dem Graph oben, Start A:

Schritt 1: Queue [A] → besuche A → Nachbarn B, D dazu
Schritt 2: Queue [B, D] → besuche B → Nachbarn C, E dazu
Schritt 3: Queue [D, C, E] → besuche D
Schritt 4: Queue [C, E] → besuche C → Nachbar F dazu
Schritt 5: Queue [E, F] → besuche E → Nachbar G dazu
Schritt 6: Queue [F, G] → besuche F
Schritt 7: Queue [G] → besuche G

Reihenfolge: A, B, D, C, E, F, G

Pfad-Eigenschaft: BFS findet kürzeste Wege nach Anzahl der Kanten in ungewichteten Graphen, sofern der Zielknoten erreichbar ist.

Komplexität (Adjazenzliste): O(V + E), jeder Knoten wird einmal besucht, jede Kante höchstens konstant oft betrachtet (bei ungerichteten Graphen einmal pro Endpunkt). Mit Adjazenzmatrix wird BFS/DFS typischerweise O(V²), weil pro Knoten alle möglichen Nachbarn geprüft werden.

DFS, Depth-First Search (in die Tiefe)

Geht so tief wie möglich, dann zurück.

function DFS(start):
    visited = {start}
    stack = [start]
    while stack not empty:
        node = stack.pop()              // Stack: LIFO
        print(node)
        for neighbor in adjacency[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                stack.push(neighbor)

Oder rekursiv (eleganter):

function DFS(node, visited):
    if node in visited: return
    visited.add(node)
    print(node)
    for neighbor in adjacency[node]:
        DFS(neighbor, visited)

Datenstruktur: Stack (LIFO) oder Rekursion (System-Stack).

Beispiel Graph oben, Start A (Nachbarn alphabetisch besucht):

Stack [A] → besuche A, push D, B (umgekehrt!) → Stack [D, B]
Stack [D, B] → pop B → besuche B, push E, C → Stack [D, E, C]
Stack [D, E, C] → pop C → besuche C, push F → Stack [D, E, F]
... → A, B, C, F, E, D, G

Achtung Reihenfolge: damit beim iterativen Stack-DFS die Nachbarn alphabetisch besucht werden, müssen sie in umgekehrter Reihenfolge gepusht werden, der zuletzt gepushte wird zuerst gepoppt.

Pfad-Eigenschaft: DFS ist NICHT für kürzeste Pfade. Aber super für: Zyklen finden, topologisches Sortieren, Zusammenhangskomponenten.

Komplexität (Adjazenzliste): O(V + E), wie BFS. Mit Adjazenzmatrix: O(V²).

BFS vs. DFS, wann was?

FrageBFSDFS
DatenstrukturQueue (FIFO)Stack (LIFO) / Rekursion
ReihenfolgeEbenenweiseIn die Tiefe
Kürzester Pfad?Ja (ungewichtet, nach Kanten)Nein
Zyklus finden?MöglichKlassisch
Topologische Sortierung?Per Kahn-Algorithmus mit QueueJa (DFS-Klassiker)
Speicher (allgemeiner Graph)O(V) (visited + Queue)O(V) (visited + Stack/Rekursion)
Speicher (Suchbaum, b/d-Notation)O(b · d) breitO(d) tief
ImplementierungIterativRekursiv oder iterativ

Faustregel: "kürzester Pfad" → BFS. "alle Pfade", "Zyklus", "Sortierung" → DFS.

Kürzester Pfad: Dijkstra (Bonus)

Bei gewichteten Graphen reicht BFS nicht. Dijkstra löst das.

function Dijkstra(start, target):
    dist[start] = 0; dist[other] = ∞
    pq = priority_queue([(0, start)])     // Min-Heap nach Distanz
    while pq not empty:
        (d, node) = pq.pop_min()
        if d > dist[node]: continue       // veralteter PQ-Eintrag, überspringen
        if node == target: return d
        for (neighbor, weight) in adjacency[node]:
            new_dist = d + weight
            if new_dist < dist[neighbor]:
                dist[neighbor] = new_dist
                pq.push((new_dist, neighbor))

Der if d > dist[node] Check filtert veraltete PQ-Einträge, wenn ein Knoten schon mit einer besseren Distanz expandiert wurde, übersprungen wir den alten Eintrag. Ohne diesen Check wird derselbe Knoten möglicherweise mehrfach aus der PQ gepoppt (wenn mehrere Distanz-Updates in der PQ landen), was die Laufzeit verschlechtert, aber die Korrektheit bei nicht-negativen Gewichten nicht verletzt.

Dijkstra braucht eine Priority Queue (Min-Heap) als Datenstruktur. Komplexität: O((V + E) log V).

Achtung: Dijkstra funktioniert NUR mit nicht-negativen Gewichten. Bei negativen Kanten → Bellman-Ford.

Wichtige Eigenschaften

Zusammenhängend:

  • Ungerichtet: jeder Knoten kann jeden anderen erreichen. (Bei BFS/DFS von einem Start: wenn am Ende alle Knoten besucht sind, ist der Graph zusammenhängend.)
  • Gerichtet: man unterscheidet stark zusammenhängend (jeder erreicht jeden über gerichtete Wege) und schwach zusammenhängend (der zugrunde liegende ungerichtete Graph ist zusammenhängend).

Zyklus: ein geschlossener Pfad, der zum Start zurückkehrt, typischerweise mit mindestens einer Kante, ohne zwischendurch Knoten zu wiederholen. In gerichteten Graphen müssen alle Kantenrichtungen eingehalten werden. DFS erkennt Zyklen, wenn ein bereits besuchter Knoten im aktuellen Pfad erreicht wird.

Baum (für ungerichtete Graphen): zusammenhängend und azyklisch. Mit n Knoten genau n-1 Kanten. (Für gerichtete Bäume / Arboreszenzen gelten andere Definitionen.)

Bipartit: Knoten lassen sich in zwei Mengen teilen, Kanten gehen nur zwischen den Mengen. BFS findet das mit 2-Färbung.

Grad eines Knotens: Anzahl Kanten, die ihn berühren. Bei gerichteten Graphen: Eingangsgrad und Ausgangsgrad.

Klausur-Tricks

Trick 1, Datenstruktur immer angeben: BFS = Queue, DFS = Stack/Rekursion. In Klausur immer dazu sagen.

Trick 2, Reihenfolge bei DFS ist nicht eindeutig. Wenn die Aufgabe DFS verlangt, gib die Nachbar-Reihenfolge an (üblich: alphabetisch oder ID-aufsteigend).

Trick 3, Visited-Set vergessen = Endlosschleife. Beim Erkunden eines Graphen IMMER markieren, welche Knoten schon besucht wurden.

Trick 4, Komplexität BFS / DFS hängt von der Repräsentation ab:

  • Adjazenzliste: O(V + E), Klausur-Standard.
  • Adjazenzmatrix: O(V²), pro Knoten alle möglichen Nachbarn prüfen.

Trick 5, Adjacency-Matrix vs. Liste:

  • Matrix: gut bei dichten Graphen oder häufigen "ist Kante drin?"-Checks. Speicher O(V²).
  • Liste: gut bei sparsen Graphen. Speicher O(V + E).

Trick 6, Wege zählen: Anzahl der Kanten in einem Pfad. Bei BFS: Anzahl der Ebenen vom Start.

Trick 7, Zyklus-Erkennung:

  • Ungerichtet: DFS, achten auf Kanten zu schon besuchten Knoten (außer Parent).
  • Gerichtet: DFS mit drei Farben (weiß/grau/schwarz).

Trick 8, Kanten-Anzahl:

  • Ungerichteter Graph mit n Knoten: max. C(n,2) = n(n-1)/2 Kanten.
  • Vollständig (alle mit allen) → "K_n".

Trick 9, Eulerweg / Eulerkreis (jede Kante genau einmal, ungerichtet):

  • Eulerweg: existiert, wenn genau 0 oder genau 2 Knoten ungeraden Grades haben, und der Graph (ohne isolierte Knoten) zusammenhängend ist.
  • Eulerkreis: braucht genau 0 Knoten ungeraden Grades, und der Graph (ohne isolierte Knoten) zusammenhängend ist.

Trick 10, Hamiltonkreis: jeden Knoten genau einmal, NP-schwer, in der Klausur Vorsicht: kein Polynom-Algorithmus bekannt.

Trick 11, Dijkstra-Voraussetzung: Dijkstra nur bei nicht-negativen Kantengewichten. Bei negativen Kanten Bellman-Ford verwenden (oder bei negativen Zyklen die Unmöglichkeit feststellen). Wird in MC-Klausuren gerne als Fallstrick eingebaut.

Wo brauchst du Graphen?

  • Maps & Routenplanung: Dijkstra, A*-Algorithmus
  • Soziale Netzwerke: Freundschafts-Graph, "Freunde von Freunden" via BFS
  • Web-Crawler: Web ist ein gerichteter Graph, Crawler benutzt BFS oder DFS
  • Compiler: Abhängigkeits-Graph zwischen Modulen, topologische Sortierung
  • AI / Pathfinding: Routensuche per Dijkstra / A*. Spiele-KI nutzt zusätzlich Spielbäume (Game Trees), eine spezielle Baumstruktur, kein allgemeiner Graph.
  • Datenbank-Joins: Query-Pläne sind Graphen
  • VLSI-Design / Circuit-Layout: physische Layouts modelliert als Graphen
  • Bioinformatik: Protein-Interaktions-Netzwerke
  • Empfehlungssysteme: User-Item-Bipartite-Graph

Faustregel: wenn die Aufgabe "Verbindungen", "Wege", "Erreichbarkeit", "Reihenfolge mit Abhängigkeiten" beinhaltet, wahrscheinlich Graph.

Teil 2·Visualisierung / Interaktiv

Interaktiv

Graph-Traversal-Spielwiese

Klick einen Knoten als Start, wähle BFS oder DFS, dann Play. Beobachte:

  • Aktueller Knoten in Vermillion (gerade besucht)
  • Bereits besucht in heller Tönung mit accent-Border
  • Frontier (Queue/Stack-Inhalt) als Boxen unten links
  • Reihenfolge der Besuche unten rechts (1., 2., 3., …)

Probier folgendes:

  • Start A, BFS → ebenenweise: A, B, D, C, E, F, G
  • Start A, DFS → in die Tiefe: A, B, C, F, E, D, G (Reihenfolge anders!)
  • Start G, BFS → wie viele Schritte bis A erreicht ist? (Antwort: 4)
  • Step-Button: einen Schritt manuell machen, statt Auto-Play
  • Speed-Toggle 1×/2×/5× für die Animation

Sieh dir den Unterschied zwischen Queue (BFS, FIFO) und Stack (DFS, LIFO) live an, das ist der Kern der beiden Algorithmen.

Interaktive Visualisierung

BFS und DFS auf einem Graphen mit besuchten Knoten und Schritt-Reihenfolge.

Faustregel zum Mitnehmen: BFS = ebenenweise (Queue, kürzester Pfad). DFS = in die Tiefe (Stack/Rekursion, Zyklen). Beide laufen in O(V + E), der Unterschied ist die Datenstruktur.


Code-Stepper: BFS mit Queue und visited-Set

BFS in Reinform: eine Queue für die Reihenfolge, ein visited-Set gegen Doppelbesuche. Wir starten auf einem kleinen 6-Knoten-Baum (A oben, B/C zweite Ebene, D/E/F dritte Ebene) und schauen wie sich Queue und visited Schritt für Schritt füllen. Klausur-Klassiker: was kommt zuerst aus der Queue?

Interaktive Visualisierung

Interaktive Komponente: probiere sie im Topic-Player oben aus.

Teil 3·Quiz / Klausurfragen

Quiz

Klausurfragen mit Lösungen (8)

F1.Welche Datenstruktur wird typisch für BFS verwendet?

Antwort: Queue (FIFO)

Erklärung: BFS = Breadth-First (ebenenweise) → Queue (FIFO). Knoten werden in der Reihenfolge ihres Entdeckens abgearbeitet. DFS dagegen nutzt Stack/Rekursion. Klausur-Klassiker: Datenstruktur immer dazu sagen.

F2.Was ist der wichtige Unterschied zwischen Adjacency Matrix und Adjacency List?

Antwort: Matrix braucht O(V²) Speicher, Liste braucht O(V+E)

Erklärung: Matrix: O(V²) Speicher unabhängig von der Kantenzahl. Liste: O(V+E), bei sparsen Graphen viel sparsamer. Matrix ist gut für 'ist Kante drin?'-Checks (O(1)). Liste für Iteration über Nachbarn (O(grad)).

F3.Welcher Algorithmus findet den kürzesten Pfad in einem ungewichteten Graph?

Antwort: BFS

Erklärung: BFS findet den kürzesten Pfad in ungewichteten Graphen, weil es ebenenweise vorgeht, der erste Treffer eines Ziels ist garantiert über minimale Kantenzahl. Dijkstra wäre für gewichtete Graphen mit nicht-negativen Gewichten.

F4.Was ist die Komplexität von BFS und DFS bei einer Adjazenzliste?

Antwort: O(V + E)

Erklärung: Mit **Adjazenzliste**: `O(V + E)`, jeder Knoten wird einmal besucht, jede Kante höchstens konstant oft betrachtet. Mit **Adjazenzmatrix** wird BFS/DFS hingegen typischerweise `O(V²)`, weil pro Knoten alle möglichen Nachbarn geprüft werden müssen. Die '+'-Notation: bei sparsen Graphen `E ll V²`, bei dichten `≈ V²`.

F5.Bei DFS, welche Reihenfolge ergibt sich auf einem Graph A-B-C wenn die Nachbarn alphabetisch durchgegangen werden, Start A?

Antwort: A, B, C

Erklärung: DFS A: besuche A → push B → pop B → besuche B → push C → pop C → besuche C. Reihenfolge: A, B, C. Bei eindeutiger Nachbar-Reihenfolge ist DFS deterministisch.

F6.Was ist eine Adjacency List im Gegensatz zur Matrix?

Antwort: Pro Knoten eine Liste seiner Nachbarn

Erklärung: Adjacency List: pro Knoten ein Array/eine Liste der direkten Nachbarn. Speicher O(V+E), iterieren über Nachbarn O(grad(v)). Antwort C wäre die Adjacency Matrix.

F7.Welcher Graph-Algorithmus brauchst du für gewichteten kürzesten Pfad mit nicht-negativen Gewichten?

Antwort: Dijkstra

Erklärung: Dijkstra ist der Standard für nicht-negative Gewichte. Bei negativen Gewichten würde Dijkstra falsch sein → dann Bellman-Ford. BFS funktioniert nur für ungewichtete Graphen.

F8.Wieviele Kanten kann ein ungerichteter, einfacher Graph mit n Knoten höchstens haben?

Antwort: `C(n,2) = n(n-1)/2`

Erklärung: Ungerichtet, ohne Mehrfachkanten und ohne Schleifen: jede Knotenpaarung kann höchstens eine Kante haben → C(n, 2) = n(n−1)/2. Bei n=5: 10 Kanten max. Ein Graph mit dieser Kantenzahl heißt **vollständig** (Kₙ).

Zur KategorieAlgorithmen.Mehr Themen entdeckenZum Themen-Hub.

UniProMax ist eine themenbasierte Lernplattform für Studierende an deutschen Unis.

Wir glauben, dass Verstehen besser ist als Auswendiglernen. Wir bauen Lerneinheiten die zeigen statt erzählen. Code, Visualisierung, Quiz. Auf Deutsch.

Marke

UniProMaxUniProMax

Themenbasiert, visuell, interaktiv.

Inhalte

  • Alle Themen (Hub)
  • Programmiergrundlagen
  • Algorithmen
  • Mathematik
  • Statistik
  • Datenbanken
  • Rechnungswesen
  • VWL

Studiengang-Filter

  • Informatik
  • Wirtschaftsinformatik
  • BWL
  • Data Science
  • VWL
  • Wirtschaftsingenieurwesen
  • Mathe
  • Psychologie
  • weitere Studiengänge folgen

Plattform

  • Mein Fortschritt
  • Impressum
  • Datenschutz
© 2026 UniProMaxAlle Systeme onlinev0.2 / Sommersemester 2026
UniProMaxUniProMaxUniProMaxUniProMax