Informatik · Klasse 9–13 · aktualisiert
Breitensuche (BFS): Ablauf und kürzeste Wege
Du führst die Breitensuche mit einer Warteschlange aus, bestimmst Abstände und Vorgänger und beurteilst, wann sie kürzeste Wege findet.
0 von 13 Aufgaben gelöst
Kurz gesagt
Die Breitensuche (BFS) durchsucht einen Graphen Ebene für Ebene. Dafür nutzt sie eine Warteschlange, die nach dem FIFO-Prinzip arbeitet. Haben alle Kanten das gleiche Gewicht, ist jede so gefundene Lösung optimal.
Wie kommst du in einem Irrgarten oder in einem Netz von Städten am schnellsten von A nach B? Die Breitensuche prüft zuerst alle Nachbarn des Starts, dann deren Nachbarn und so weiter. So geht sie Schicht für Schicht nach außen. Du lernst, wie du sie von Hand ausführst und wann sie einen kürzesten Weg liefert.
Deine Lernziele
Hake ab, was du schon kannst. Löst du alle Aufgaben eines Abschnitts, hakt Mela das Ziel für dich ab.
4 Abschnitte
Ein Graph besteht aus Knoten (den Punkten) und Kanten (den Verbindungen zwischen den Knoten). Die Breitensuche (englisch breadth-first search, kurz BFS) durchläuft die Knoten eines Graphen. Sie bearbeitet immer zuerst alle Knoten der gleichen Ebene. Anders als die Tiefensuche folgt sie nicht einem Pfad in die Tiefe.
Dafür braucht sie eine Warteschlange. Mit enqueue legst du ein Objekt hinein, mit dequeue holst du eines zurück und entfernst es. Die Warteschlange arbeitet nach dem FIFO-Prinzip: Das Objekt, das zuerst hineingelegt wurde, kommt zuerst wieder heraus. Das ist wie an einer Kasse: Wer sich zuerst anstellt, wird zuerst bedient.
Der Ablauf: Im ersten Schritt wählst du den Startknoten, markierst ihn als gesehen und speicherst ihn in der Warteschlange. Im zweiten Schritt nimmst du einen Knoten vom Beginn der Warteschlange. Alle bisher unmarkierten Nachfolger dieses Knotens hängst du ans Ende der Warteschlange an und markierst sie dabei als gesehen. In einem ungerichteten Graphen sind die Nachfolger die Nachbarn. Dann wiederholst du den zweiten Schritt. Findest du das gesuchte Element, brichst du ab. Ist die Warteschlange leer, endet die Suche mit „nicht gefunden“.
Unser Beispielgraph ist ungerichtet. Die Nachbarn stehen in dieser Reihenfolge in der Eingabe: A: D, B, C; B: A, E, F; C: A, G; D: A, H; E: B; F: B, H; G: C; H: D, F. Start ist A. Diese Reihenfolge ist eine Wahl der Aufgabe, keine Regel der Breitensuche.
Definition
Warteschlange
Eine Datenstruktur, die ihre Objekte nach dem FIFO-Prinzip (First In – First Out) zurückgibt: Das Objekt, das zuerst mit enqueue hineingelegt wurde, kommt mit dequeue zuerst wieder heraus.
Beispiel: Beispielgraph mit Start A
- 1Start: A ist gesehen. Warteschlange: A
- 2A entnehmen; neu entdeckt: D, B, C. Warteschlange: D B C
- 3D entnehmen; neu entdeckt: H. Warteschlange: B C H
- 4B entnehmen; neu entdeckt: E, F. Warteschlange: C H E F
- 5C entnehmen; neu entdeckt: G. Warteschlange: H E F G
- 6H, E und F entnehmen; nichts Neues. Warteschlange: G
- 7G entnehmen; nichts Neues. Warteschlange: leer
- 8Besuchsreihenfolge: A D B C H E F G
Merke: Den nächsten Knoten nimmst du immer vom Beginn der Warteschlange. Neue Knoten hängst du am Ende an.
Teste dich
Die Breitensuche arbeitet Ebene für Ebene. Der Startknoten ist Ebene 0. Der Knotenabstand gibt an, über wie viele Kanten ein Knoten vom Startknoten entfernt ist. Im Beispielgraphen ist der Abstand von A zu D 1 Kante, von A zu H 2 Kanten und von A zu G 2 Kanten. Der Knotenabstand bezieht sich immer auf den Startknoten.
Ein zweites Beispiel ist ein Städtegraph mit Start Hannover. Dort werden die Iterationsschritte Ebene für Ebene gezählt, und der Index des Iterationsschritts entspricht dem Knotenabstand. Iterationsschritt 0: Hannover (Knotenabstand 0). Iterationsschritt 1: Frankfurt, Hamburg, Berlin (Knotenabstand 1). Iterationsschritt 2: Zürich, Stuttgart, Mannheim, Wien (Knotenabstand 2). Iterationsschritt 3: München, Dresden (Knotenabstand 3). Achtung: Hier ist ein Schritt eine ganze Ebene. Im Ablauf des ersten Beispiels (Start A) ist dagegen jede Zeile nur eine einzelne Entnahme aus der Warteschlange. Die Nummer der Entnahme ist nicht der Abstand: D wird als Zweiter entnommen, hat aber Abstand 1.
Bei gerichteten Graphen ist der Knotenabstand zwischen zwei verschiedenen Knoten nicht unbedingt symmetrisch. Bei einem nicht zusammenhängenden Graphen ist der Knotenabstand nur innerhalb jeder Zusammenhangskomponente definiert (das ist ein Teil des Graphen, dessen Knoten miteinander verbunden sind), also nur für Knoten, die vom Startknoten aus erreichbar sind.
Den Vorgänger eines Knotens notierst du so: Es ist der Knoten, von dem aus er entdeckt wurde. Im Beispielgraphen ist A der Vorgänger von D, B und C. Der Vorgänger von H ist D, der Weg zu H ist A → D → H. Den Weg zu einem Knoten erhältst du als Kette der Vorgänger von A bis zu diesem Knoten. Verbindest du jeden Knoten außer dem Startknoten mit dem Knoten, von dem aus er gefunden wurde, entsteht der Breitensuchbaum.
Definition
Vorgänger
Der Vorgänger eines Knotens ist der Knoten, von dem aus er bei der Suche entdeckt wurde.
| Knoten | Abstand zu A | Vorgänger |
|---|---|---|
| A | 0 | – |
| D | 1 | A |
| B | 1 | A |
| C | 1 | A |
| H | 2 | D |
| E | 2 | B |
| F | 2 | B |
| G | 2 | C |
Teste dich
Die Breitensuche durchsucht dem Startknoten näher gelegene Knoten vor weiter entfernten. Jede durch Breitensuche gefundene Lösung hat den kürzesten Abstand zum Wurzelknoten, also zum Startknoten. Sie kann zwischen zwei Knoten einen kürzesten Pfad finden, wenn die Kanten ungewichtet sind.
Ein Kantengewicht ist eine Zahl an einer Kante, die zum Beispiel Kosten oder eine Länge angibt. Sind alle Kantengewichte gleich, so ist jede durch Breitensuche gefundene Lösung optimal: In diesem Fall ist die Lösung, die am nächsten zum Ausgangsknoten liegt, auch die mit den geringsten Kosten. Bei verschiedenen Gewichten muss das Ergebnis, das am nächsten zum Startknoten liegt, nicht unbedingt das Ergebnis mit den geringsten Pfadkosten sein. Dafür gibt es die uniforme Kostensuche, eine Erweiterung der Breitensuche für Graphen mit gewichteten Kanten. Ihre Optimalität ist nur für nicht-negative Kantengewichte garantiert.
Den Weg selbst erhältst du, wenn du dir den bei der Suche gegangenen Weg speicherst. In einem Irrgarten sind die Zellen die Knoten. Für jede besuchte Zelle merkst du dir ihre Entfernung vom Startpunkt oder die Nachbarzelle, von der aus sie betreten wurde. Den kürzesten Lösungsweg erhältst du, indem du vom Zielpunkt aus die besuchten Zellen zurück bis zum Startpunkt verfolgst.
Warum die Ebenenreihenfolge das garantiert, wird hier nicht Schritt für Schritt bewiesen. Merke dir die Aussage und ihre Bedingung.
Beispiel: Ausgedachtes Beispiel: Der Umweg ist billiger
- 1Erfundener Graph mit Kantengewichten: A–B hat Gewicht 10, A–C hat Gewicht 1, C–B hat Gewicht 1. Gesucht: B, Start A.
- 2Die Breitensuche entdeckt B schon beim Entnehmen von A. B hat Abstand 1.
- 3Der Weg A → B hat 1 Kante und die Kosten 10.
- 4Der Weg A → C → B hat 2 Kanten und die Kosten 1 + 1 = 2.
- 5Die Breitensuche liefert den Weg mit den wenigsten Kanten, nicht den mit den geringsten Kosten.
Merke: Bei ungewichteten Kanten oder lauter gleichen Gewichten ist jede durch Breitensuche gefundene Lösung optimal.
Teste dich
Die Laufzeit der Breitensuche beträgt O(|V|+|E|). Dabei ist |V| die Anzahl der Knoten und |E| die Anzahl der Kanten. Die Schreibweise O(…) heißt Landau-Notation. Sie gibt an, wie die Anzahl der Schritte oder der Speicherplatz von der Größe des Problems abhängt. Für diese Analyse wird angenommen, dass die Eingabe ein endlicher Graph ist, der explizit als Adjazenzliste oder ähnlich dargestellt wird. Eine Adjazenzliste gibt für jeden Knoten eine Liste aller seiner Nachbarn an, bei gerichteten Graphen seiner Nachfolger. Wie groß |E| ist, hängt davon ab, wie dünn der Graph ist: O(|E|) kann zwischen O(1) und O(|V|²) liegen.
Der Speicherplatzverbrauch beträgt O(|V|), weil alle bisher entdeckten Knoten gespeichert werden. Das gilt, wenn die Anzahl der Knoten im Voraus bekannt ist und man sich merkt, welche Knoten schon in der Warteschlange waren. Es kommt zusätzlich zu dem Platz hinzu, den der Graph selbst braucht. Vermische das nicht mit der Laufzeit.
Grenzen: Für Verfahren, bei denen die Knoten erst während der Suche erzeugt werden (zum Beispiel Branch-&-Bound), ist die Breitensuche wegen des großen Platzverbrauchs meist ungeeignet. Die iterative Tiefensuche kommt meist mit deutlich weniger Speicher aus. Bei Kantengewichten liefert die Breitensuche nicht unbedingt den billigsten Weg.
Hat jeder Knoten nur endlich viele Alternativen, ist die Breitensuche vollständig. Wenn eine Lösung existiert, wird sie gefunden, auch in einem unendlichen Graphen. Existiert keine Lösung, divergiert die Breitensuche bei einem unendlichen Graphen: Sie kommt dann zu keinem Ergebnis.
| Größe | Angabe | Hinweis |
|---|---|---|
| Laufzeit | O(|V|+|E|) | Annahme: endlicher Graph als Adjazenzliste oder ähnlich |
| Speicher | O(|V|) | Zusätzlich zum Graphen; alle entdeckten Knoten werden gespeichert |
| Grenze | meist ungeeignet | Wenn Knoten erst während der Suche erzeugt werden |
Merke: Die Laufzeit hängt von Knoten und Kanten ab (O(|V|+|E|)). Der Speicher hängt vor allem von den gespeicherten Knoten ab.
Teste dich
Alles auf einen Blick
Breitensuche
Warteschlange
Sie arbeitet nach dem FIFO-Prinzip. Der zuerst hineingelegte Knoten kommt zuerst wieder heraus.
Ablauf
Startknoten markieren und speichern, dann Knoten vom Beginn nehmen und unmarkierte Nachfolger ans Ende hängen.
Abstand
Er zählt die Kanten vom Startknoten und bezieht sich immer auf diesen.
Vorgänger
Das ist der Knoten, von dem aus ein Knoten entdeckt wurde. Seine Kette ergibt den Weg.
Kürzeste Wege
Bei ungewichteten oder gleich gewichteten Kanten ist jede gefundene Lösung optimal.
Aufwand
Die Laufzeit beträgt O(|V|+|E|) (Adjazenzliste). Der Speicher beträgt O(|V|) unter den genannten Bedingungen. Die Breitensuche ist meist ungeeignet, wenn Knoten erst während der Suche entstehen.
Musteraufgabe · Schritt für Schritt
Ausgedachter Graph mit Start S: Reihenfolge, Abstände, Vorgänger
- 1Erfundener ungerichteter Graph, Nachbarn in dieser Reihenfolge: S: P, Q; P: S, R; Q: S, R, T; R: P, Q; T: Q.
- 2Start: S ist gesehen. Warteschlange: S
- 3S entnehmen; neu entdeckt: P, Q. Warteschlange: P Q
- 4P entnehmen; S ist gesehen, R ist neu. Warteschlange: Q R
- 5Q entnehmen; S und R sind gesehen, T ist neu. Warteschlange: R T
- 6R entnehmen; P und Q sind gesehen, nichts Neues. Warteschlange: T
- 7T entnehmen; Q ist gesehen, nichts Neues. Warteschlange: leer
- 8Besuchsreihenfolge: S P Q R T
- 9Abstände von S: S 0; P und Q 1; R und T 2
- 10Vorgänger: P von S, Q von S, R von P, T von Q. Weg zu T: S → Q → T
Fehler finden
Prüfe die Aussagen zum Ablauf der Breitensuche In einer Zeile steckt ein Fehler. Tippe sie an.
Fehler in Zeile 3Der Knoten wird am falschen Ende entnommen. Richtig: Du nimmst den nächsten Knoten vom Beginn der Warteschlange (FIFO).
Lückentext
Wähl in jeder Lücke das passende Wort und prüf dann deine Antworten.
Weil die Warteschlange nach dem FIFO-Prinzip arbeitet, nimmt die Breitensuche den nächsten Knoten vom der Warteschlange. Für Verfahren, bei denen die Knoten erst während der Suche erzeugt werden, ist sie meist ungeeignet, weil sie viel braucht. Sind alle Kantengewichte , so ist jede durch Breitensuche gefundene Lösung optimal.
Karteikasten
Erst selbst überlegen, dann umdrehen.
Übung mit Feedback