21. Januar 2010

Werbung
Generischer MST-Algorithmus
T
T0
T 00
V1
T 000
V2
Wald F
EADS
ľErnst W. Mayr
3.2 Generischer minimaler Spannbaum-Algorithmus
445/598
3.3 Kruskal’s Algorithmus
algorithm Kruskal (G, w) :=
sortiere die Kanten nach aufsteigendem Gewicht in eine Liste L
initialisiere Wald F = {Ti , i = 1, . . . , n}, mit Ti = {vi }
MSB:=∅
for i := 1 to length(L) do
{v, w} := Li
x := Baum ∈ F , der v enthält; co x :=Find(v) oc
y := Baum ∈ F , der w enthält; co y :=Find(w) oc
if x 6= y then
MSB:=MSB ∪ {{v, w}}
Union(x, y) co gewichtete Vereinigung oc
fi
od
EADS
ľErnst W. Mayr
3.3 Kruskal’s Algorithmus
446/598
Korrektheit: Falls die Gewichte eindeutig sind (w(·) injektiv), folgt
die Korrektheit direkt mit Hilfe der “blauen“ und “roten“ Regel.
Ansonsten Induktion über die Anzahl |V | der Knoten:
√
Ind. Anfang: |V | klein:
Sei r ∈ R, Er := {e ∈ E; w(e) < r}.
Es genügt zu zeigen:
Sei T1 , . . . , Tk ein minimaler Spannwald für Gr := {V, Er } (d.h.,
wir betrachten nur Kanten mit Gewicht < r). Sei weiter T ein
MSB von G, dann gilt die
Hilfsbehauptung: Die Knotenmenge eines jeden Ti induziert in T
einen zusammenhängenden Teilbaum, dessen Kanten alle Gewicht
< r haben.
EADS
ľErnst W. Mayr
3.3 Kruskal’s Algorithmus
447/598
Beweis der Hilfsbehauptung:
Sei Ti =: (Vi , Ei ). Wir müssen zeigen, dass Vi in T einen
zusammenhängenden Teilbaum induziert. Seien u, v ∈ Vi zwei
Knoten, die in Ti durch eine Kante e verbunden sind. Falls der
Pfad in T zwischen u und v auch Knoten 6∈ Vi enthält (also der
von Vi induzierte Teilgraph von T nicht zusammenhängend ist),
dann enthält der in T durch Hinzufügen der Kante e entstehende
Fundamentalkreis notwendigerweise auch Kanten aus E \ Er und
ist damit gemäß der “roten“ Regel nicht minimal! Da Ti
zusammenhängend ist, folgt damit, dass je zwei Knoten aus Vi in
T immer durch einen Pfad verbunden sind, der nur Kanten aus Er
enthält.
EADS
ľErnst W. Mayr
3.3 Kruskal’s Algorithmus
448/598
Zeitkomplexität: (mit n = |V |, m = |E|)
Sortieren
O(m) Find-Operationen
n − 1 Unions
m log m = O(m log n)
O(m)
O(n log n)
Satz 103
Kruskal’s MSB-Algorithmus hat die Zeitkomplexität
O((m + n) log n).
Beweis:
s.o.
EADS
ľErnst W. Mayr
3.3 Kruskal’s Algorithmus
449/598
Beispiel 104 (Kruskals Algorithmus)
8
7
9
2
4
11
7
6
4
10
8
1
⇓
8
4
8
EADS
ľErnst W. Mayr
14
2
4
11
7 7
2
6
1
1
2
minimaler (nicht eindeutiger)
Spannbaum
7
6
9
8
5
14
4
10
3
2
3.3 Kruskal’s Algorithmus
450/598
3.4 Prim’s Algorithmus
algorithm PRIM-MSB (G, w) :=
initialisiere Priority Queue PQ mit Knotenmenge V und
Schlüssel +∞, ∀v ∈ V
wähle Knoten r als Wurzel (beliebig)
Schlüssel k[r] := 0
Vorgänger[r] := nil
while P Q 6= ∅ do
u := ExtractMin(P Q)
for alle Knoten v, die in G zu u benachbart sind do
if v ∈ P Q and w({u, v}) < k[v] then
Vorgänger[v] := u
k[v] := w({u, v})
fi
od
od
EADS
ľErnst W. Mayr
3.4 Prim’s Algorithmus
451/598
Beispiel 105 (Prim’s Algorithmus)
+∞
v7
4
2
+∞
v0
0
11
7
8
+∞ 7
v6
8
v1
+∞ 1
EADS
ľErnst W. Mayr
v8
6
v2
+∞
+∞
v5
9
14
4
2
10
v3
+∞
Ausgangszustand:
+∞ alle Schlüssel = +∞
v4
aktueller Knoten u:
Startknoten: r (= v0 )
452/598
Beispiel 105 (Prim’s Algorithmus)
+∞
v7
4
2
+∞
v0
0
+∞ 7
v6
8
11
v8
6
7
8
v1
+∞ 1
4
8
v7
4
11
v2
+∞ 2
+∞ 7
v6
6
7
8
v1
8
EADS
ľErnst W. Mayr
v8
1
v2
+∞
9
14
4
2
+∞
v0
+∞
v5
4
2
10
v3
+∞
+∞
v5
9
Ausgangszustand:
+∞ alle Schlüssel = +∞
v4
aktueller Knoten u:
Startknoten: r (= v0 )
suche u := FindMin(P Q)
und entferne u aus P Q
+∞ setze Schlüssel der Nach14
v4
barn in P Q mit
w({u, v}) < Schlüssel[v]:
10
(v1 = 8, v7 = 4)
v3
+∞
452/598
Beispiel 105 (Prim’s Algorithmus)
4
+∞ 7
v6
8
v7
4
2
+∞
v0
11
v8
6
7
8
v1
v2
+∞ 2
8
7
v6
1
8
8
v7
1
2
+∞
v0
4
11
7
8
6
v1
8
EADS
ľErnst W. Mayr
v8
1
v2
+∞
4
2
+∞
v5
suche u := FindMin(P Q)
und entferne u aus P Q
+∞ setze Schlüssel der Nach14
v4
barn in P Q mit
w({u, v}) < Schlüssel[v]:
10
(v1 = 8, v7 = 4)
v3
+∞
+∞
v5
suche u := FindMin(P Q)
9
und entferne u aus P Q
+∞ setze Schlüssel der Nach14
v4
barn in P Q mit
w({u, v}) < Schlüssel[v]:
10
(v6 = 8)
v3
+∞
9
452/598
Beispiel 105 (Prim’s Algorithmus)
8
8
v7
1
2
+∞
v0
7
v6
11
v8
8
v1
v2
+∞
1
8
4
6
7
2
2
1
v0
7
v7
v6
2
2
11
6
7
8
v1
8
EADS
ľErnst W. Mayr
v8
1
v2
+∞
4
2
+∞
v5
suche u := FindMin(P Q)
und entferne u aus P Q
+∞ setze Schlüssel der Nach14
v4
barn in P Q mit
w({u, v}) < Schlüssel[v]:
10
(v6 = 8)
v3
+∞
7
v5
suche u := FindMin(P Q)
9
und entferne u aus P Q
+∞ setze Schlüssel der Nach14
v4
barn in P Q mit
w({u, v}) < Schlüssel[v]:
10
(v3 = 4, v5 = 7, v8 = 2)
v3
4
9
452/598
Beispiel 105 (Prim’s Algorithmus)
2
1
v0
7
v7
v6
v5
2
2
11
v8
8
v1
v2
+∞
1
8
4
6
7
2
2
v7
1
v0
7
v6
3
v8
11
8
v1
7
EADS
ľErnst W. Mayr
v5
v2
1
6
2
suche u := FindMin(P Q)
und entferne u aus P Q
+∞ setze Schlüssel der Nach14
v4
barn in P Q mit
w({u, v}) < Schlüssel[v]:
10
(v3 = 4, v5 = 7, v8 = 2)
v3
9
4
7
4
6
7
7
suche u := FindMin(P Q)
und entferne u aus P Q
+∞ setze Schlüssel der Nach14
v4
barn in P Q mit
w({u, v}) < Schlüssel[v]:
10
(v1 = 7, v2 = 6)
v3
9
4
452/598
Beispiel 105 (Prim’s Algorithmus)
2
v7
1
v0
7
v6
3
v8
11
8
v1
v2
1
7
v5
4
6
7
2
6
2
v7
1
v0
7
v6
3
7
EADS
ľErnst W. Mayr
9
4
6
v2
1
4
7
14
v1
7
suche u := FindMin(P Q)
und entferne u aus P Q
+∞ setze Schlüssel der Nach14
v4
barn in P Q mit
w({u, v}) < Schlüssel[v]:
10
(v1 = 7, v2 = 6)
v3
9
v5
v8
11
8
7
2
2
10
v3
10
v4
suche u := FindMin(P Q)
und entferne u aus P Q
setze Schlüssel der Nachbarn in P Q mit
w({u, v}) < Schlüssel[v]:
(v2 = 2, v4 = 10)
452/598
Beispiel 105 (Prim’s Algorithmus)
2
v7
1
v0
7
v6
3
v5
v8
11
8
14
v1
2
2
2
v7
1
7
v6
3
8
v1
1
EADS
ľErnst W. Mayr
4
10
v3
v2
1
9
14
6
7
10
v4
7
v5
v8
11
suche u := FindMin(P Q)
und entferne u aus P Q
setze Schlüssel der Nachbarn in P Q mit
w({u, v}) < Schlüssel[v]:
(v1 = 1)
10
v3
v2
1
7
10
v4
suche u := FindMin(P Q)
und entferne u aus P Q
setze Schlüssel der Nachbarn in P Q mit
w({u, v}) < Schlüssel[v]:
(v2 = 2, v4 = 10)
9
4
6
7
v0
7
5
452/598
Beispiel 105 (Prim’s Algorithmus)
2
v7
1
v0
7
v6
3
8
14
v1
EADS
ľErnst W. Mayr
4
10
v3
v2
6
9
14
6
v1
7
v5
v8
7
8
7
v6
3
11
10
v4
5
2
v7
suche u := FindMin(P Q)
und entferne u aus P Q
setze Schlüssel der Nachbarn in P Q mit
w({u, v}) < Schlüssel[v]:
solche Nachbarn existieren
nicht
10
v3
v2
1
1
10
v4
suche u := FindMin(P Q)
und entferne u aus P Q
setze Schlüssel der Nachbarn in P Q mit
w({u, v}) < Schlüssel[v]:
(v1 = 1)
9
4
6
7
v0
v5
v8
11
1
7
5
452/598
Beispiel 105 (Prim’s Algorithmus)
2
v7
1
v0
7
3
v1
v7
8
5
7
v6
3
v5
v8
v1
EADS
ľErnst W. Mayr
4
10
v3
v2
6
9
14
6
7
9
v4
suche u := FindMin(P Q)
und entferne u aus P Q
setze Schlüssel der Nachbarn in P Q mit
w({u, v}) < Schlüssel[v]:
(v4 = 9)
10
v3
v2
11
10
v4
suche u := FindMin(P Q)
und entferne u aus P Q
setze Schlüssel der Nachbarn in P Q mit
w({u, v}) < Schlüssel[v]:
solche Nachbarn existieren
nicht
9
14
6
2
v0
v5
4
6
7
1
7
v8
11
8
v6
5
452/598
Beispiel 105 (Prim’s Algorithmus)
2
v7
1
v0
7
3
10
v3
v2
6
2
v0
8
v6
v5
v8
v1
EADS
ľErnst W. Mayr
14
v4
10
v3
v2
6
8
4
6
7
suche u := FindMin(P Q)
und entferne u aus P Q
setze Schlüssel der Nachbarn in P Q mit
w({u, v}) < Schlüssel[v]:
(v4 = 9)
5
7
3
11
9
v4
14
v1
v7
9
4
6
7
1
v5
v8
11
8
v6
Endzustand:
suche u := FindMin(P Q)
und entferne u aus P Q,
damit ist P Q leer und der
Algorithmus beendet
5
3.4 Prim’s Algorithmus
452/598
Korrektheit: ist klar.
Zeitkomplexität:
n ExtractMin
O(m) sonstige Operationen inclusive DecreaseKey
Implementierung der Priority Queue mittels Fibonacci-Heaps:
Initialisierung
ExtractMins
DecreaseKeys
Sonstiger Overhead
EADS
ľErnst W. Mayr
O(n)
O(n log n) (≤ n Stück)
O(m) (≤ m Stück)
O(m)
3.4 Prim’s Algorithmus
453/598
Satz 106
Sei G = (V, E) ein ungerichteter Graph (zusammenhängend,
einfach) mit Kantengewichten w. Prim’s Algorithmus berechnet,
wenn mit Fibonacci-Heaps implementiert, einen minimalen
Spannbaum von (G, w) in Zeit O(m + n log n) (wobei
n = |V |, m = |E|). Dies ist für m = Ω(n log n) asymptotisch
optimal.
Beweis:
s.o.
EADS
ľErnst W. Mayr
3.4 Prim’s Algorithmus
454/598
3.5 Prim’s Algorithmus, zweite Variante
Die Idee der folgenden Variante von Prim’s Algorithmus ist:
Lasse die Priority Queues nicht zu groß werden.
Seien dazu G = (V, E), |V | = n, |E| = m, w Gewichtsfunktion,
und k ein Parameter, dessen Wert wir erst später festlegen werden.
Der Algorithmus arbeitet nun in Phasen wie folgt:
1
Initialisiere eine Schlange von Bäumen, jeder Baum anfangs
ein (Super-) Knoten. Zu jedem Baum initialisiere eine Priority
Queue (Fibonacci-Heap) mit den Nachbarn der Knoten im
Baum, die selbst nicht im Baum sind, als Elementen und
jeweils dem Gewicht einer leichtesten Kante zu einem Knoten
im Baum als Schlüssel.
2
Markiere jeden Baum in der Schlange mit der Nummer der
laufenden Phase.
EADS
ľErnst W. Mayr
3.5 Prim’s Algorithmus, zweite Variante
455/598
3
Bestimme k für die Phase
4
while vorderster Baum in der Schlange hat laufende
Phasennummer do
lasse ihn wachsen, solange seine Priority Queue höchstens
k Elemente enthält (und noch etwas zu tun ist)
if Priority Queue zu groß (mehr als k Elemente) then
füge Baum mit inkrementierter Phasennummer am
Ende der Schlange ein
fi
od
5
Falls Phasensprung“: Schrumpfe alle Bäume zu Superknoten,
”
reduziere Kantenmenge (d.h., behalte zwischen zwei Knoten
jeweils nur die leichteste Kante)
6
Beginne nächste Phase mit Schritt 1.!
EADS
ľErnst W. Mayr
3.5 Prim’s Algorithmus, zweite Variante
456/598
wenn groß genug
hinten anstellen
..
Endemarkierung
EADS
ľErnst W. Mayr
Endemarkierung
falls
Phasensprung
schrumpfen und
nächste Phase
3.5 Prim’s Algorithmus, zweite Variante
457/598
Analyse des Zeitbedarfs:
Sei t die Anzahl der Bäume in der Schlange zu Beginn einer Phase.
Betrachte die Schlange von Bäumen:
v
T1
T2
···
Ti
···
Tt
Abgesehen von den Operationen, die bei der Vereinigung von
Superknoten anfallen, beträgt der Zeitaufwand pro Phase O(m).
EADS
ľErnst W. Mayr
3.5 Prim’s Algorithmus, zweite Variante
458/598
Vereinigung zweier Superknoten, z.B. T1 und T2 :
Für jeden (Super-)Knoten v in T2 ’s Priority Queue:
√
1 v ∈ T :
(nichts zu tun)
1
2
v in Priority Queue von T1 : DecreaseKey. Hilfsdatenstruktur:
für alle Knoten in den Priority Queues ein Zeiger auf den
Superknoten, in dessen Priority Queue der Knoten letztmals
am Anfang der Schlange stand.
3
sonst: Einfügen
EADS
ľErnst W. Mayr
3.5 Prim’s Algorithmus, zweite Variante
459/598
Betrachte Knoten mit Halbkanten“: jede Halbkante kommt nur
”
1x in allen Bäumen der Queue vor. Mit m Kanten ergeben sich 2m
Halbkanten.
v
e
m
Kanten
EADS
ľErnst W. Mayr
v
→
e
e
und
2m
Halbkanten
v
=
b
e
Kante aus zwei
Halbkanten
3.5 Prim’s Algorithmus, zweite Variante
460/598
Zeitaufwand pro Phase (mit Bildung der Superknoten zu Beginn):
Initialisierung: O(m)
ExtractMin: < t Operationen
sonstige Priority Queue-Operationen, Overhead: Zeit O(m)
Da die Priority Queues höchstens k Elemente enthalten, wenn
darauf eine teure“ Priority Queue-Operation durchgeführt wird,
”
sind die Kosten pro Phase
O(t log k + m) .
2m
Setze k = 2 t (damit t log k = 2m). Damit sind die Kosten pro
Phase O(m).
EADS
ľErnst W. Mayr
3.5 Prim’s Algorithmus, zweite Variante
461/598
Wieviele Phasen führt der Algorithmus aus?
t ist die Anzahl der Superknoten am Anfang einer Phase, t0 sei
diese Zahl zu Beginn der nächsten Phase. Sei a die
durchschnittliche Anzahl ursprünglicher Knoten in jeder der t
Priority Queues zu Anfang der Phase, a0 entsprechend zu Beginn
der nächsten Phase.
Wir haben:
1
a=
2
t0 ≤
2m
t
2m
k
EADS
ľErnst W. Mayr
(mit Ausnahme ev. der letzten Phase)
3.5 Prim’s Algorithmus, zweite Variante
462/598
Also:
a0 =
2m
2m
≥ k = 2 t = 2a
0
t
Für die erste Phase ist a = 2m
n , für jede Phase ist a ≤ n − 1. Also
ist die Anzahl der Phasen
2m
(i)
≤ 1 + min i; log2 (n − 1) ≤
.
n
n
o
(i)
Setzen wir β(m, n) := min i; log2 n ≤ m
n , dann gilt
n
β(m, n) ≤ log n für n ≤ m ≤
.
2
∗
EADS
ľErnst W. Mayr
3.5 Prim’s Algorithmus, zweite Variante
463/598
Satz 107
Für gewichtete, zusammenhängende (ungerichtete) Graphen mit n
Knoten, m Kanten kann ein minimaler Spannbaum in Zeit
O(min{m · β(m, n), m + n log n}) bestimmt werden.
EADS
ľErnst W. Mayr
3.5 Prim’s Algorithmus, zweite Variante
464/598
Herunterladen