Beide können mit genau demselben generischen Algorithmus wie folgt implementiert werden:
Inputs:
G: Graph
s: Starting vertex (any for Prim, source for Dijkstra)
f: a function that takes vertices u and v, returns a number
Generic(G, s, f)
Q = Enqueue all V with key = infinity, parent = null
s.key = 0
While Q is not empty
u = dequeue Q
For each v in adj(u)
if v is in Q and v.key > f(u,v)
v.key = f(u,v)
v.parent = u
Für Prim pass f = w(u, v)
und für Dijkstra pass f = u.key + w(u, v)
.
Eine andere interessante Sache ist, dass Generic oben auch Breadth First Search (BFS) implementieren kann, obwohl dies übertrieben wäre, da eine teure Prioritätswarteschlange nicht wirklich erforderlich ist. Um den generischen Algorithmus in BFS umzuwandeln, übergeben Sie, f = u.key + 1
was dem Erzwingen aller Gewichte auf 1 entspricht (dh BFS gibt die minimale Anzahl von Kanten an, die zum Durchlaufen von Punkt A nach B erforderlich sind).
Intuition
Hier ist eine gute Möglichkeit, über den obigen generischen Algorithmus nachzudenken: Wir beginnen mit zwei Buckets A und B. Setzen Sie zunächst alle Ihre Scheitelpunkte in B, sodass der Bucket A leer ist. Dann verschieben wir einen Scheitelpunkt von B nach A. Betrachten Sie nun alle Kanten von Scheitelpunkten in A, die zu den Scheitelpunkten in B übergehen. Wir haben die eine Kante anhand einiger Kriterien aus diesen Überkreuzungskanten ausgewählt und den entsprechenden Scheitelpunkt von B nach A verschoben A. Wiederholen Sie diesen Vorgang, bis B leer ist.
Eine Brute-Force-Methode zur Umsetzung dieser Idee wäre die Aufrechterhaltung einer Prioritätswarteschlange der Kanten für die Scheitelpunkte in A, die zu B übergeht. Dies wäre natürlich problematisch, wenn der Graph nicht dünn wäre. Die Frage wäre also, ob wir stattdessen die Prioritätswarteschlange der Eckpunkte beibehalten können. Dies in der Tat können wir als unsere Entscheidung schließlich ist, welchen Scheitelpunkt wir aus B auswählen sollen.
Historischer Zusammenhang
Es ist interessant, dass die generische Version der Technik hinter beiden Algorithmen konzeptionell so alt ist wie 1930, selbst wenn es keine elektronischen Computer gab.
Die Geschichte beginnt mit Otakar Borůvka, der einen Algorithmus für einen Freund seiner Familie benötigte, um herauszufinden, wie Städte im Land Mähren (heute Teil der Tschechischen Republik) mit kostengünstigen Stromleitungen verbunden werden können. Er veröffentlichte seinen Algorithmus 1926 in einer mathematikbezogenen Zeitschrift, da es damals keine Informatik gab. Dies machte Vojtěch Jarník auf sich aufmerksam, der über eine Verbesserung des Borůvka-Algorithmus nachdachte und ihn 1930 veröffentlichte. Tatsächlich entdeckte er denselben Algorithmus, den wir heute als Prims Algorithmus kennen, der ihn 1957 wieder entdeckte.
Unabhängig davon musste Dijkstra 1956 ein Programm schreiben, um die Fähigkeiten eines neuen Computers zu demonstrieren, den sein Institut entwickelt hatte. Er fand es cool, wenn der Computer Verbindungen findet, um zwischen zwei Städten der Niederlande zu reisen. Er entwarf den Algorithmus in 20 Minuten. Er erstellte ein Diagramm von 64 Städten mit einigen Vereinfachungen (da sein Computer 6-Bit war) und schrieb Code für diesen Computer von 1956. Er hat seinen Algorithmus jedoch nicht veröffentlicht, da es in erster Linie keine Fachzeitschriften für Informatik gab und er der Meinung war, dass dies möglicherweise nicht sehr wichtig ist. Im nächsten Jahr lernte er das Problem kennen, Klemmen neuer Computer so anzuschließen, dass die Länge der Drähte minimiert wurde. Er dachte über dieses Problem nach und entdeckte Jarník / Prim 'wieder. s Algorithmus, der wieder dieselbe Technik verwendet wie der Algorithmus mit dem kürzesten Pfad, den er ein Jahr zuvor entdeckt hatte. Ererwähnte, dass beide seiner Algorithmen ohne Verwendung von Stift oder Papier entworfen wurden. Im Jahr 1959 veröffentlichte er beiden Algorithmen in einem Papier , das nur 2 und eine halbe Seite lang ist.