Warum sollte die Breitensuche in der Zeit

9

Es wird oft gesagt (zB in Wikipedia ) , dass die Laufzeit der Breitensuche (BFS) auf einem Graph G=(V,E) ist O(|V|+|E|) . Jeder verbundene Graph hat jedoch |V||E|+1 und selbst in einem nicht verbundenen Diagramm betrachtet BFS niemals einen Scheitelpunkt außerhalb der Komponente, die den Startscheitelpunkt enthält. Diese Komponente enthält höchstens |E| Kanten, so enthält es höchstens |E|+1 Eckpunkte, und dies sind die einzigen, die der Algorithmus besuchen wird.

Dies bedeutet, dass |V|+|E|2|E|+1 , warum sagen wir nicht, dass die Laufzeit nur O(|E|) ?

Dies kam in Kommentaren zu einer Frage zur Laufzeit des Disjkstra-Algorithmus zum Ausdruck .

David Richerby
quelle
Warum nehmen Sie an, dass es einen Startscheitelpunkt gibt? BFS bei maximalem Übereinstimmungsproblem beginnt beispielsweise mit allen nicht übereinstimmenden Eckpunkten im Hopcroft-Karp-Algorithmus. In diesem Fall, wenn der gegebene Graph
eine Gesamtstruktur
2
@narekBojikian Während BFS auf verschiedene Arten verwendet werden kann, hat es als eigenständiger Algorithmus so gut wie immer einen Startscheitelpunkt.
David Richerby

Antworten:

9

BFS wird normalerweise wie folgt beschrieben (aus Wikipedia ).

 1  procedure BFS(G,start_v):
 2      let Q be a queue
 3      label start_v as discovered
 4      Q.enqueue(start_v)
 5      while Q is not empty
 6          v = Q.dequeue()
 7          if v is the goal:
 8              return v
 9          for all edges from v to w in G.adjacentEdges(v) do
10             if w is not labeled as discovered:
11                 label w as discovered
12                 w.parent = v
13                 Q.enqueue(w)

Das Problem ist etwas subtil: Es versteckt sich in Zeile 3! Die Frage ist, welche Datenstruktur werden wir verwenden, um zu speichern, welche Eckpunkte entdeckt wurden?

falseΘ(|V|)|V||E|O(|V|+|E|)

Θ(|V|)O(|V||E|)O(|E|2)|V|4|V||E||V|3

O(log|V|)O(|E|log|V|)

c|E|+1c+2c+4c++2|E|4|E| O(1)O(|E|)

O(|E|)4|E|O(|E|)O(|V|+|E|)

David Richerby
quelle
1
Ich denke, es könnte zu stark sein, um zu behaupten, dass Hash-Tabellen in der Praxis eine schlechte Cache-Leistung haben. Wenn mit Verkettung (dh verknüpften Listen) implementiert, stimme ich zu. Aber wenn es mit einem kontinuierlichen Speicherblock und offener Adressierung implementiert wird, nicht so sehr.
Juho
Wunderbare Antwort! Eine Randnotiz: Dynamisch große Hash-Tabellen sind in der Tat eine gute Wahl, nicht nur wenn es viele kleine Komponenten gibt, sondern auch, wenn der Hash-Wert für einen Scheitelpunkt durch eine vernünftige Konstante begrenzt ist, und dies kommt häufig vor. Schöne Antwort!
Carlos Linares López
1
David, ich hatte vor Jahren ähnliche Gedanken. Ich denke, die Antwort liegt in historischen Perspektiven.
Kelalaka