Das Union-Find-Problem

Werbung
Informatik I
9. Kapitel
Das Union-Find-Problem
Rainer Schrader
Zentrum für Angewandte Informatik Köln
9. Juli 2008
1 / 61
2 / 61
union-find-Problem
union-find-Problem
Gliederung
• in einigen Anwendungen müssen Objekte in Äquivalenzklassen
• Definitionen und Anwendungen
eingeteilt werden
• einfache Ansätze
• bei der Konstruktion werden dazu äquivalente Teilmengen vereinigt
• Pfadkomprimierung
• wir werden zwei konkrete Beispiele behandeln
• minimal-aufspannende Bäume
3 / 61
4 / 61
union-find-Problem
union-find-Problem
• erzeuge(x ):
• erzeuge eine neue Menge {x }
• x darf dabei nicht Element einer anderen Menge sein
gegeben:
• der Repräsentant von {x } ist x
• endliche Grundmenge E
• vereinige(x , y ):
• Familie S = {S1 , S2 , . . . , Sk } von disjunkten Teilmengen Si ⊆ E
• vereinige die Mengen, die x und y enthalten, Sx und Sy , zu
einer neuen Menge Sx ∪ Sy .
• jede Menge Si ist durch einen eindeutigen Repräsentanten
x ∈ Si gekennzeichnet
• der Repräsentant von Sx ∪ Sy ist ein beliebiges Element aus
Sx ∪ Sy
gesucht:
• Datenstruktur zur Unterstützung der folgenden Operationen:
• setze S ← (S \ {Sx , Sy }) ∪ {Sx ∪ Sy }
• finde(x ):
• liefere den Repräsentanten der (eindeutigen) Menge, die
x enthält
5 / 61
6 / 61
union-find-Problem
union-find-Problem
Anwendung:
ein (ungerichteter) Graph G = (V , E ) besteht aus:
• einer endlichen Menge V von Knoten und
• einer Menge E ⊆ {{v , w } | v , w ∈ V , v 6= w } von Kanten
Parameter für Effizienzmessungen:
• n: Anzahl der erzeuge-Operationen
• m: Gesamtzahl der erzeuge-, vereinige- und finde-Operationen
Beispiel:
• V = {1, 2, 3, 4, 5}
• E = {{1, 2}, {1, 3}, {2, 3}, {2, 4}, {2, 5}, {3, 4}, {3, 5}, {4, 5}}
Beobachtungen:
• m≥n
• nach n − 1 vereinige-Operationen bleibt nur eine einzelne Menge übrig
• d.h. es gibt höchstens n − 1 vereinige-Operationen
1
7 / 61
2
3
4
5
8 / 61
union-find-Problem
union-find-Problem
Offensichtlich gilt:
• ein (v1 , vk )-Pfad in G = (V , E ) ist eine Folge v1 , v2 , . . . , vk von
• seien G1 = (V1 , E1 ), G2 = (V2 , E2 ), . . . , Gk = (Vk , Ek ) die
Knoten mit vi ∈ V (1 ≤ i ≤ k ) und {vi , vi +1 } ∈ E (1 ≤ i ≤ k − 1)
verschiedenen Zusammenhangskomponenten von G = (V , E ),
• gilt vi 6= vj für i 6= j , so heißt v1 , v2 , . . . , vk ein (v1 , vk )-Weg in G
• dann folgt
• der Graph G ist zusammenhängend, falls zu jedem Paar
Vi ∩ Vj = ∅,
v , w ∈ V ein (v , w )-Pfad in G existiert
Ei ∩ Ej = ∅
für 1 ≤ i , j ≤ k , i 6= j
und
• ein Graph G 0 = (V 0 , E 0 ) heißt Untergraph eines Graphen
0
V =
0
G = (V , E ) falls V ⊆ V und E ⊆ E
z
[
Vi ,
i =1
• eine Zusammenhangskomponente von G ist ein knoten- und
E =
k
[
Ei ,
i =1
• d.h. G kann in seine Zusammenhangskomponenten partitioniert
kantenmaximaler zusammenhängender Untergraph von G
werden
9 / 61
10 / 61
union-find-Problem
union-find-Problem
• Beispiel: ein Graph mit vier Zusammenhangskomponenten:
Komponenten(G)
a
b
e
c
d
g
f
h
j
für alle v ∈ V do
erzeuge(v)
end do
i
für alle {u,v} ∈ E do
if finde(u) 6= finde(v)
end do
Gesucht sind die Zusammenhangskomponenten eines Graphen.
11 / 61
then
vereinige(u,v)
12 / 61
union-find-Problem
union-find-Problem
Danach lässt sich wie folgt feststellen, ob zwei Knoten u und v in der
gleichen Zusammenhangskomponente sind:
Gliederung
• Definitionen und Anwendungen
zusammenhängend(u, v )
• einfache Ansätze
if
finde(u) = finde(v)
then return TRUE
else return FALSE
endif
• Pfadkomprimierung
• minimal-aufspannende Bäume
13 / 61
14 / 61
union-find-Problem
union-find-Problem
Dann gilt:
(1) erzeuge(x ):
1. Ansatz
• setze Element(x ) = x
Die Elemente der Grundmenge seien durchnumeriert.
• in O(1)
(2) finde(x ):
• wir verwenden ein Feld Element(1, . . . , n)
• in O(1)
• Element(i ) enthält den Repräsentanten der Menge, die i enthält
(3) vereinige(x , y ):
• am Anfang ist Element(i ) mit „leer” oder Null initialisiert
• sei a = finde(x )
• sei b = finde(y )
• durchlaufe das Feld Element und ändere die Einträge a in b
• Laufzeit für vereinige(x , y ) : O(n)
15 / 61
16 / 61
union-find-Problem
union-find-Problem
Beispiel: S = {{c, h, e, b}, {f , g, d }}
2. Ansatz
• jede Menge wird als lineare Liste dargestellt
• der erste Knoten der Liste ist ihr Repräsentant
• jeder Knoten der Liste besteht aus drei Komponenten:
c
h
e
f
g
d
b
• dem Element der Menge
• einem Zeiger auf das nächste Element der Liste
• einem Zeiger zurück auf den Repräsentanten
• jede Liste besitzt einen Kopf- und einen Schwanzzeiger auf den Anfang
bzw. das Ende
• Elemente sind durch einen Zeiger gegeben
17 / 61
18 / 61
union-find-Problem
union-find-Problem
(3) vereinige(x , y ) : hänge die Liste von x an die von y
• sei a =
• sei b =
• sei z =
Dann gilt:
(1) erzeuge(x ) in
O(1):
finde(y )
tail(b)
• setze next(z ) auf head(a)
• erzeuge eine neue Liste, die nur aus x besteht
• biege alle Repräsentantenzeiger der Liste a auf b um
• setze Repräsentantenzeiger auf x
• Laufzeit für vereinige(x , y ) : O(Länge der Liste(x ))
• setze Nextzeiger auf Null
(2) finde(x ) in
finde(x )
O(1):
• setze y =
Repräsentantenzeiger von x
f
19 / 61
g
d
c
h
e
b
20 / 61
union-find-Problem
union-find-Problem
Beispiel für eine Folge von 2n − 1 Operationen mit Θ(n 2 ) Laufzeit:
• wir zählen nur das Fortschreiben der Zeiger auf die Repräsentanten
• die Elemente seien x1 , x2 , . . . , xn
• ; mittlere Laufzeit von Θ(n) pro Operation
• offensichtlich ist es keine blendende Idee, einfach die erste Menge an
Operation
erzeuge(x1 )
erzeuge(x2 )
..
.
erzeuge(xn )
vereinige(x1 , x2 )
vereinige(x2 , x3 )
..
.
vereinige(xn−1 , xn )
Laufzeit: n +
Pn−1
i =1
i =n+
n(n−1)
2
die zweite zu hängen
Anzahl der Updates
1
1
..
.
1
1
2
..
.
n−1
• besser: hänge die kürzere an die längere
• wir merken uns dazu zu jeder Menge die Anzahl ihrer Elemente
• eine einzelne Vereinige-Operation kann dann immer noch Ω(n) Zeit
dauern, falls beide Mengen Ω(n) viele Elemente haben, aber:
Satz
Mit der obigen Variation benötigt eine Folge von m erzeuge-, finde- und
vereinige-Operationen (davon n erzeuge-Operationen) O(m + n log n) Zeit.
= Θ(n 2 )
21 / 61
union-find-Problem
22 / 61
union-find-Problem
Satz
Mit der obigen Variation benötigt eine Folge von m erzeuge-, finde- und
vereinige-Operationen (davon n erzeuge-Operationen) O(m + n log n) Zeit.
3. Ansatz: Jede Menge wird durch einen Baum repräsentiert
Beweis:
• sei x ∈ E
• bei jeder Vereinigung, bei der x involviert ist, wächst die Menge auf
• die Knoten enthalten die Elemente
• die Wurzel enthält den Repräsentanten
mindestens die doppelte Größe
• ; höchstens log n solcher Vereinigungen
• ; der Repräsentantenzeiger von x wird höchstens log n mal
• zusätzliche Sohn-Vater-Zeiger, die Wurzel zeigt auf sich selbst.
fortgeschrieben
• ; höchstens O(n log n) Schritte für Vereinige-Operationen
• zusätzlich O(m) für die anderen Operationen mit konstantem
Zeitbedarf
• somit ergibt sich eine Laufzeit von O(m + n log n)
23 / 61
24 / 61
union-find-Problem
union-find-Problem
Beispiel:
S = {{a, b, c, d }, {e, f , g}, {h, i }, {j }}
a
b
c
e
h
f
i
Laufzeiten
j
• erzeuge: O(1)
d
• vereinige (ohne finde): O(1)
g
vereinige(c, f ): Mache den einen Repräsentanten zum Sohn des anderen:
• Finde(x ): Θ(Anzahl der Knoten auf dem Pfad von x zur Wurzel)
a
b
c
d
e
f
g
25 / 61
26 / 61
union-find-Problem
union-find-Problem
worst-case: (wie vorher)
for i=1 to n,
erzeuge(i );
for i=1 to n-1
vereinige(i,i+1)
1
2
3
Verbesserung: „Vereinigung nach Größe”
end for
end for
• wir merken uns für jeden Baum die Anzahl seiner Knoten
• entweder in einem Feld oder in der Wurzel
4
• wir hängen bei „vereinige” den kleineren unter den größeren
Vereinige(1,2)
2
3
4
Vereinige(3,4)
4
Lemma
1
3
Seien T1 , . . . , Tj die nach k vereinige-Operationen entstandenen Bäume,
sei x ∈ S und Tx der Teilbaum unter x . Dann gilt:
2
Vereinige(2,3)
3
(i) |Tx | ≥ 2Höhe(x )
4
1
(ii) Höhe(x ) ≤ log n
2
(iii) es gibt höchstens
1
n
Elemente der Höhe h.
2h
Finde(1) benötigt dann Θ(n) Zeit.
27 / 61
28 / 61
union-find-Problem
union-find-Problem
(i) |Tx | ≥ 2Höhe(x )
(i) |Tx | ≥ 2Höhe(x )
(ii) Höhe(x ) ≤ log n
(iii) es gibt höchstens
• Induktion über die Anzahl k der vereinige-Operationen:
• für k = 0 sind alle Bäume von „finde” erzeugt und (i) ist erfüllt
n
Elemente der Höhe h.
2h
• gelte also (i) nach k − 1 Schritten
• im k -ten Schritt werden zwei Bäume vereinigt, es genügt zu zeigen:
Beweis:
(ii) folgt aus (i): Höhe(x ) ≤ log |Tx | ≤ log n
(iii)
• wenn x die Wurzel des neuen Baumes T 0 ist und sich die Höhe von
x erhöht, dann gilt (i) immer noch
folgt aus (i):
• wenn sich die Höhe von x erhöht, so hat x einen Sohn y erhalten
• seien x , y zwei Elemente der Höhe h
• dann ist Tx ∩ Ty = ∅
• damit folgt für t = |{x : Höhe(x ) = h}| :
n≥
X
mit Höhe(y ) = Höhe(x ) − 1
• per Konstruktion war |Ty | ≤ |Tx | und per Induktion |Ty | ≥ 2Höhe(x )−1
• dann ist auch |Tx | ≥ 2Höhe(x )−1
|Tx | ≥ t · 2h .
• somit
Höhe(x )=h
• und somit t ≤
√
|Tx0 | = |Tx | + |Ty | ≥ 2 · 2Höhe(x )−1 = 2Höhe(x )
n
.
2h
29 / 61
30 / 61
union-find-Problem
union-find-Problem
Satz
Gliederung
Mit Ansatz 3 kann eine Folge von n − 1 Vereinige- und
m Finde-Operationen in O(n + m log n) Schritten bearbeitet werden.
• Definitionen und Anwendungen
Beweis:
• einfache Ansätze
• jede Vereinige-Operation kostet O(1) Zeiteinheiten
• die Höhe eines jeden Baums ist höchstens log n
• Pfadkomprimierung
• minimal-aufspannende Bäume
• damit benötigt jede finde-Operation O(log n) Schritte
• daraus ergibt sich eine Laufzeit von O(n + m log n).
31 / 61
32 / 61
union-find-Problem
union-find-Problem
4. Ansatz: Pfadkomprimierung
4. Ansatz: Pfadkomprimierung
• bei einer finde-Operation laufen wir von einem Knoten v1 entlang eines
vorher:
nach finde(h):
Pfades v1 , v2 , . . . , vk zur Wurzel
a
• wir machen vi , 1 ≤ i < k zu Söhnen von vk .
b
e
vorher:
c
e
e
nach finde(b):
a
f
d
g
h
d
b
c
d
jj
c
b
c
e
g
f
i
h
jj
d
k
i
k
a
b
• der Aufwand erhöht sich dadurch (verdoppelt sich)
• zahlt sich aber bei späteren finde-Operationen aus
a
33 / 61
34 / 61
union-find-Problem
union-find-Problem
Iterierter Logarithmus
• wir verwenden eine Abschätzung mittels amortisierter Kosten
•
F (0) = 1, F (1) = 2, F (2) = 4, F (3) = 16, F (4) = 65536, F (i ) = 2F (i −1)
• zur Vereinfachung nehmen wir an:
• log∗ n = min{k : F (k ) ≥ n}
• die Laufzeit einer finde-Operation eines Elements der Tiefe k
beträgt k
Zur Veranschaulichung:
• wir sprechen auch von „Kosten” k
2·
• wir müssen somit die Gesamtosten abschätzen
F (k ) = 2
• dafür verteilen wir die anfallenden Kosten auf verschiedene Konten
22
• F (4) = 22 , F (4) ist nicht
• und schätzen die Gesamtkontenstände ab
··2
)
k
“` ´2 ”2 ` ´2
22
= 42 = 162 = 256
• F (5) = 265536 1080 ≈ Anzahl der Atome im Universum
• wir verwenden dazu die folgenden Funktionen:
• log∗ n misst, wie oft logarithmiert werden muss, um eine Zahl ≤ 1 zu
erhalten
• beispielsweise: log∗ (n) ≤ 5 für n ≤ 265536 .
35 / 61
36 / 61
union-find-Problem
union-find-Problem
• sei W die Menge der nach den Vereinige-Operationen ohne
• wir fassen die Knoten zu Gruppen 0, 1, . . . zusammen
• Gruppe i enthält alle Knoten x mit F (i − 1) + 1 ≤ rang(x ) ≤ F (i )
Pfadkomprimierung entstandenen Bäume
• sei rang(x ) die Höhe von x in W
• in W wachsen die Ränge von Knoten auf einem Pfad zur Wurzel
Gruppe
0
1
2
3
..
.
i
..
.
streng monoton
• dies bleibt auch nach Pfadkomprimierung erhalten
vorher:
1
nach findset(h):
b
a
4
c
3
d
0
1
b
c
g
0
f
1
0
jj
g
h
2
i
k
h
2
3
0 e
4
a
1
e
f
i
jj
k
0
0
0
0
0
d
0
Knoten vom Rang
0 und 1
2
3 und 4
5, . . . , 16
..
.
F (i − 1) + 1, . . . , F (i )
..
.
• da log∗ n = min{i : F (i ) ≥ n} existieren höchstens log∗ n Gruppen
0
0
38 / 61
37 / 61
union-find-Problem
union-find-Problem
Verbuchung
• wir legen ein allgemeines Konto und für jeden Knoten v ∈ T ein
F(i+1)
separates Konto an
• sei v1 . . . vk , vk +1 der Weg von einem Knoten v1 zur Wurzel vk +1
• die Kosten k werden zunächst den Knoten v1 , . . . , vk zugeordnet
1
1
F(i)
• der Knoten vk gibt seine Kosten an das allgemeine Konto zurück
• ebenso jeder Knoten vi , für den vi +1 in einer anderen Gruppe liegt
1
F(i-1)
• d.h. jeder Knoten vi , i ≤ k − 1, für den vi +1 in der gleichen Gruppe
F(i+1)
1
liegt, erhält eine Kosteneinheit
• das allgemeine Konto erhält den Rest der Gesamtkosten k
• da maximal log∗ n Gruppen existieren, sind dies höchstens log∗ n + 1.
1
F(i)
1
F(i-1)
39 / 61
40 / 61
union-find-Problem
union-find-Problem
• sei N (i ) die Anzahl der Knoten in Gruppe i ,
• d.h. N (i ) = |{x : F (i − 1) + 1 ≤ Höhe(x ) ≤ F (i )}|
• nach früherem Lemma gibt es höchstens 2nh Knoten der Höhe h
Dann gilt:
• jeder Knoten, dem eine Kosteneinheit zugeordnet wird, erhält einen
neuen Vater, der einen höheren Rang hat als der alte
• sei x in Gruppe i , d.h. rang(x ) ∈ {F (i − 1) + 1, . . . , F (i )},
• mit
P∞
i =0
xi =
1
1−x
für |x | < 1 folgt:
• spätestens nach Zuweisung von F (i ) − F (i − 1) Kosteneinheiten ist
der Vater von x in einer anderen Gruppe,
• spätere Väter erst recht
F (i )
X
N (i ) ≤
h=F (i −1)+1
• danach werden x keine Kosten mehr zugewiesen
≤
n
2F (i −1)
=
find
n
2h
∞
X
1
2k
k =1
n
2F (i −1)
= n/F (i )
vereinige
(per Definition von F (i ))
41 / 61
42 / 61
union-find-Problem
union-find-Problem
Satz
Mit dem Ansatz 4 kann eine Folge von n − 1 vereinige- und
m finde-Operationen in O(n log∗ n + m log∗ n) Schritten bearbeitet werden.
Gliederung
Beweis:
• Definitionen und Anwendungen
• jedem Knoten in Gruppe i werden höchstens F (i ) − F (i − 1) ≤ F (i )
• einfache Ansätze
Kosten zugeordnet
• Gesamtkosten der Gruppe i : höchstens N (i )F (i ) ≤ n
• da es höchstens log∗ n Gruppen gibt, sind die Gesamtkosten aller
• Pfadkompromierung
• minimal-aufspannende Bäume
Gruppen höchstens n log∗ n
• dem allgemeinen Konto werden bei jeder Finde-Operation höchstens
log∗ n + 1 Kosten zugewiesen.
Da log∗ (n) ≤ 5 für n ≤ 1080 , haben wir für alle praktischen Fälle konstante
Laufzeit pro Operation.
43 / 61
44 / 61
union-find-Problem
union-find-Problem
• die Städte entsprechen den Knoten eines Graphen
• wir müssen Kanten so auswählen, dass
• gegeben seien n Städte (Knotenpunkte)
• der entstehende Graph zusammenhängend ist
• jeder Knoten an mindestens einer Kante hängt
• es soll ein Telefonnetz konstruiert werden, so dass Teilnehmer aus je
zwei Städten miteinander telefonieren können
• keine Kreise entstehen
(aus Kostengründen)
• wobei andere Städte als Vermittlungspunkte dienen können
• ein Graph G = (V , E ) heißt
• zusätzlich seien Kosten cij = cji ≥ 0 gegeben, die angeben, wie teuer
• aufspannend, wenn jeder Knoten an einer Kante hängt oder
V nur einen Knoten enthält
es ist, eine Leitung zwischen den Städten i und j zu legen.
• Wald, wenn er keine Kreise enthält
• gesucht ist eine Realisierung mit minimalen Kosten
• Baum, wenn er ein zusammenhängender Wald ist
• wir suchen somit einen minimal aufspannenden Baum (minimal
bzgl. der Kantengewichte)
46 / 61
45 / 61
union-find-Problem
union-find-Problem
Beispiel
Berechnung eines minimal aufspannenden Baums
Sei T der von den roten Kanten erzeugte Baum:
Baum = ∅
/* Liste von Kanten /*
ZH = ∅
/*Liste von Teilmengen von Knoten/*
for v ∈ V do
füge die Menge {v} als neue Menge zu ZH hinzu
endfor
while |ZH| > 1 do
suche Kante {v, w} ∈ E mit minimalen Kosten
lösche v,w aus E
bestimme W_1 = finde(v)
bestimme W_2 = finde(w)
if W_1 6= W_2 do
ersetze in ZH
W_1 und W_2
durch W_1 ∪ W_2
füge {v, w} zu Baum hinzu
endif
endwhile
8
b
7
c
d
2
4
9
11
a
i
7
e
14
4
6
10
8
h
1
g
2
f
c(T ) = 37, aber der Baum ist nicht eindeutig: z.B. kann {b, c} durch {a, h} ersetzt werden.
47 / 61
48 / 61
union-find-Problem
union-find-Problem
Lemma
(i) nach Iteration i des Algorithmus bilden ZH und die Kanten in
„Baum” einen aufspannenden Wald aus n − i Bäumen,
Lemma
(ii) jeder aufspannende Baum T eines zusammenhängenden Graphen
G auf n Knoten hat n − 1 Kanten.
Sei T ein Baum und e ∈
/ T eine Kante. Dann enthält T ∪ e höchstens
einen Kreis.
Beweis:
Beweis: (per Induktion)
• angenommen C1 ∪ e, C2 ∪ e sind zwei Kreise, die durch Hinzufügen
(i) zu Beginn ist Baum = ∅ und ZH besteht aus allen isolierten Knoten
von e entstanden sind
√
• da kein Knoten aus ZH entfernt wird, bleibt ZH aufspannend
• dann enthält auch C1 ∪ C2 ⊆ E (T ) einen Kreis. • betrachte eine vereinige-Operation:
• es werden 2 Bäume durch eine Kante verbunden, wenn die
Endknoten der Kante vorher in unterschiedlichen Bäumen lagen
√
• damit fällt die Anzahl der Bäume um genau 1
50 / 61
49 / 61
union-find-Problem
union-find-Problem
Lemma
(i) nach Iteration i des Algorithmus bilden ZH und die Kanten in
„Baum” einen aufspannenden Wald aus n − i Bäumen
Satz
(ii) jeder aufspannende Baum T eines zusammenhängenden Graphen
G auf n Knoten hat n − 1 Kanten.
Sei G = (V , E ) ein zusammenhängender Graph. Der obige Algorithmus
liefert einen minimal aufspannenden Baum.
Beweis:
Beweis:
• nach dem vorigen Lemma liefert der Algorithmus einen aufspannenden
(ii) wende den Algorithmus auf T an
Baum von G.
• nach (i) folgt:
• „Baum” enthält n − 1 Kanten
• und ist ein aufspannender Baum
• damit folgt, dass auch T n − 1 Kanten enthält
51 / 61
52 / 61
union-find-Problem
union-find-Problem
• sei T der vom Algorithmus konstruierte aufspannende Baum
• sei T 0 ein aufspannender Baum minimalen Gewichts mit
Der Algorithmus enthält folgende Operationen:
|T ∩ T 0 | maximal
• angenommen T 6= T 0
• betrachte die Reihenfolge, in der der obige Algorithmus die Kanten
• Zeile 7: finde_Minimum(S) (z.B. durch Heap)
• Zeile 8: lösche_Min-Operation
durchsucht
• Zeilen 9 und 10: finde-Operation
• Zeile 12: vereinige-Operation
• dann gibt es eine erste Kante e ∈ T mit e ∈
/ T0
• da T 0 aufspannend ist, enthält T 0 ∪ e genau einen Kreis K
• da T kreisfrei ist, gibt es wiederum eine Kante e 0 ∈ K , die nicht in
• Zeile 13: einfüge-Operation (etwa durch verkettete Listen)
T liegt
• wir verwenden einen min-Heap und
• eine union-find-Datenstruktur
• dann muß ce ≤ ce 0 gelten, da sonst der Algorithmus e 0 ausgewählt
hätte
• damit ist T 00 = (T 0 \ e 0 ) ∪ e ein aufspannender Baum mit
c(T 00 ) ≤ c(T 0 ),
• der einen größeren Schnitt mit T hat. 54 / 61
53 / 61
union-find-Problem
union-find-Problem
Kruskals Algorithmus
Kruskals Algorithmus
(1)
(2)
Initialisiere eine lineare Liste T
eine Union-Find-Struktur auf V mit
konstruiere min-Heap der Kanten
setze k:= 0
E
und
{{v_1},. . ., {v_n}}
mit Bewertung
c
while k 6= n - 1 do
{u, v} := Wurzel des min-Heaps
entferne {u, v} aus Heap
stelle Heapstruktur wieder her
A= finde(u),
B= finde(v)
(8)
if A 6= B then
T = T ∪ {u, v}
k = k + 1
(9)
vereinige (A, B)
end if
(10) end while
(3)
(4)
(5)
(6)
(7)
(1)
Initialisiere eine lineare Liste T
eine Union-Find-Struktur auf V mit
(2)
konstruiere min-Heap der Kanten
setze k:= 0
(3)
(4)
(5)
(6)
(7)
while k 6= n - 1 do
{u, v} := Wurzel des min-Heaps
Laufzeitanalyse:
entferne {u, v} aus Heap
stelle Heapstruktur wieder her
• sei |E | = m, |V | = n , m ≥ n − 1
A= finde(u),
• (1) und (2) in O(n) bzw. O(m)
B= finde(v)
if A 6= B then
• sei t Anzahl der Durchläufe von (3)-(10):
T = T ∪ {u, v}
• es ist t ≤ m
k = k + 1
(4)-(5) O(t )
vereinige (A, B)
(8)
(9)
end if
(10) end while
E
und
{{v_1},. . ., {v_n}}
mit Bewertung
(6)
O(t log m)
(7) 2t Finde-Befehle
(8)-(9)
55 / 61
c
O(n) +
n − 1 vereinige-Befehle
56 / 61
union-find-Problem
union-find-Problem
Laufzeitanalyse:
• sei |E | = m, |V | = n , m ≥ n − 1
• (1) und (2) in O(n) bzw. O(m)
• sei t Anzahl der Durchläufe von (3)-(10):
• es ist t ≤ m
(4)-(5)
(6)
• enthält G sehr viele Kanten (m = Θ(n 2 )), so benötigt Kruskals
O(t )
O(t log m)
Algorithmus
O(n 2 log n) Schritte
• der nächste Algorithmus von Prim benötigt stets O(n 2 ) Schritte
(7) 2t Finde-Befehle
(8)-(9) O(n) + n − 1 vereinige-Befehle
• er ist damit für dichte Graphen optimal
Satz
Kruskals Algorithmus hat eine Laufzeit von in O(m log n).
Beweis:
Die Laufzeit wird von den Heap-Operationen dominiert. Sie beträgt somit
O(m log m) = O(m log n).
58 / 61
57 / 61
union-find-Problem
union-find-Problem
Prims Algorithmus
Initialisiere:
T_1 = {u}, u beliebig
T
= ∅
Billig(v) = c(u, v) für alle v
Billig(u) = +∞
Ende(v)
= u für alle v 6= u
• die Bäume T2 , . . . , Tk bestehen bei Prim immer aus einzelnen Knoten
• es wird stets die billigste Kante hinzugefügt, die T1 mit einem der
anderen Knoten verbindet
• zur Vereinfachung setzen wir voraus, dass je zwei Knoten durch eine
Kante verbunden sind
6= u
for
i = 1 to
n-1 do
suche v mit Billig(v) minimal
füge v zu T_1 und {v, Ende(v)} zu T
setze Billig(v) = +∞
für w ∈ V r T_1 do
if c(v, w) < Billig(w) then do
Billig(w) = c(v, w)
Ende(w)
= v
endif
endfor
endfor
• (andernfalls fügen wir fehlende Kante mit Kosten +∞ hinzu)
• für v 6= T1 enthält
• Billig(v ) die Kosten der billigsten Kanten zwischen v und T1
• Ende(v ) deren zweiten Endpunkt
59 / 61
hinzu
60 / 61
union-find-Problem
Satz
Prims Algorithmus hat eine Laufzeit von in O(n 2 ).
Beweis:
Der Algorithmus durchläuft zwei Schleifen der Länge n.
61 / 61
Herunterladen