Die Algorithmen von BFS und Dijkstra sind einander sehr ähnlich; sie sind beide ein Sonderfall des A*-Algorithmus.
Der A*-Algorithmus ist nicht nur allgemeiner; er verbessert die Leistung des Dijkstra-Algorithmus in einigen Situationen, was aber nicht immer der Fall ist; im allgemeinen Fall ist der Dijkstra-Algorithmus asymptotisch genauso schnell wie A*.
Der Dijkstra-Algorithmus hat 3 Argumente. Wenn Sie jemals ein Netzwerkverzögerungszeitproblem gelöst haben:
class Solution:
def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int:
Die Methode A* hat 2 zusätzliche Argumente:
function aStar(graph, start, isGoal, distance, heuristic)
queue new PriorityQueue()
queue.insert(start, 0)
# hash table to keep track of the distance of each vertex from vertex "start",
#that is, the sum of the weight of edges that needs to be traversed to get from vertex start to each other vertex.
# Initializes these distances to infinity for all vertices but vertex start .
distances[v] inf ( v graph | v <> start)
# hash table for the f-score of a vertex,
# capturing the estimated cost to be sustained to reach the goal from start in a path passing through a certain vertex. Initializes these values to infinity for all vertices but vertex "start".
fScore[v] inf ( v graph | v <> start)
# Finally, creates another hash table to keep track, for each vertex u, of the vertex through which u was reached.
parents[v] null ( v graph)
A* benötigt zwei zusätzliche Argumente, a distance function
et un heuristic
. Beide tragen zur Berechnung des sogenannten f-score bei. Dieser Wert ist eine Mischung aus den Kosten für das Erreichen des aktuellen Knotens u von der Quelle aus und den erwarteten Kosten, die erforderlich sind, um das Ziel von u aus zu erreichen.
Durch die Kontrolle dieser beiden Argumente können wir entweder BFS oder Dijkstra's Algorithmus (oder keines von beiden) erhalten. Für beide gilt, dass die heuristic
muss eine Funktion sein, die identisch gleich 0 ist, etwa so
lambda(v) 0
Beide Algorithmen lassen nämlich jegliche Vorstellung von oder Informationen über die Entfernung der Eckpunkte zum Ziel völlig außer Acht.
Bei den Entfernungsmetriken stellt sich die Situation anders dar:
-
Dijkstras Algorithmus verwendet das Gewicht der Kante als Entfernungsfunktion, daher müssen wir etwas übergeben wie
distance = lambda(e) e.weight
-
BFS berücksichtigt nur die Anzahl der durchlaufenen Kanten, was gleichbedeutend damit ist, dass alle Kanten das gleiche Gewicht haben, nämlich gleich 1! Und so können wir
distance = lambda(e) 1
A* gewinnt nur in einigen Kontexten einen Vorteil, in denen wir zusätzliche Informationen haben, die wir irgendwie nutzen können. Wir können A* nutzen, um die Suche schneller zum Ziel zu führen, wenn wir Informationen über die Entfernung von allen oder einigen Eckpunkten zum Ziel haben.
Beachten Sie, dass in diesem speziellen Fall der Schlüsselfaktor darin besteht, dass die Scheitelpunkte zusätzliche Informationen mit sich führen (ihre Position, die feststeht), die bei der Schätzung ihrer Entfernung zum endgültigen Ziel helfen können. Dies trifft nicht immer zu und ist bei allgemeinen Graphen in der Regel nicht der Fall. Anders ausgedrückt, die zusätzlichen Informationen stammen hier nicht aus dem Graphen, sondern aus dem Fachwissen.
The key, here and always, is the quality of the extra information
captured by the Heuristic function: the more reliable and closer
to real distance the estimate, the better A* performs.