Informatik II - SS 2016
(Algorithmen & Datenstrukturen)
Vorlesung 16 (17.6.2016)
Graphenalgorithmen IV
(MST, Prioritätswarteschlangen)
Fabian Kuhn
Algorithmen und Komplexität
Fabian Kuhn
Informatik II, SS 2016
Minimaler Spannbaum
Gegeben: Zus.-hängender, ungerichteter Graph πΊ = π, πΈ, π€ mit
Kantengewichten π€ βΆ πΈ → β
Minimaler Spannbaum π» = π½, π¬π» :
• Spannbaum mit kleinstem Gesamtgewicht
1
1
2
3
3
9
3
15
7
8
4
2
6
1
6
5
8
Fabian Kuhn
6
9
Informatik II, SS 2016
7
2
Basis-MST-Algorithmus
Invariante:
Algorithmus hat zu jeder Zeit eine Kantenmenge π΄, so dass
π΄ Teilmenge eines minimalen Spannbaums ist.
Basis-MST-Algorithmus:
π΄ = ∅
while π΄ ist kein Spannbaum do
Finde sichere Kante π’, π£ für π΄
π΄ = π΄ ∪ π’, π£
return π΄
• Invariante ist eine gültige Schleifeninvariante
• Invariante + Abbruchbedingung βΉ π΄ ist ein MST!
Fabian Kuhn
Informatik II, SS 2016
3
Sichere Kanten
Annahmen:
• πΊ = π, πΈ, π€ ist zus.-h., unger. Graph mit Kantengewichten π€ π
• π΄ ist Teilmenge (Teilgraph) eines MST
Theorem: Sei π, π β π ein Schnitt, so dass π΄ keine Schnittkanten
enthält und sei π’, π£ , π’ ∈ π, π£ ∈ π β π eine leichte Schnittkante
bezüglich π, π β π . Dann ist π’, π£ eine sichere Kante für π΄.
1
1
2
15
3
9
3
3
7
8
4
2
6
6
1
5
8
Fabian Kuhn
6
9
7
Informatik II, SS 2016
4
Kruskal’s MST-Algorithmus
π΄ = ∅
while π΄ ist
π = π’, π£
so dass
π΄ = π΄∪
kein Spannbaum do
ist Kante mit kleinstem Gewicht,
π΄ ∪ π’, π£ keinen Zyklus enthält
π’, π£
• Wir müssen zeigen, dass π eine sichere Kante für π΄ ist
Fabian Kuhn
Informatik II, SS 2016
5
Union-Find / Disjoint Sets Datentyp
Verwaltet eine Partition von Elementen
Operationen:
• create
• U.makeSet(x)
• U.find(x)
• U.union(S1, S2)
: erzeugt eine leere Union-Find-DS
: fügt Menge {π₯} zur Partition hinzu
: gibt Menge mit Element π₯ zurück
: vereinigt die Mengen π1 und π2
• Details dazu werden in der Algorithmentheorie besprochen…
Fabian Kuhn
Informatik II, SS 2016
6
Kruskal mit Union-Find
Kruskals Algorithmus
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
π΄ = ∅
U = create new
for all π’ ∈ π do
U.makeSet(π’)
Sortiere Kanten aufsteigend nach Kantengewicht
for all π = π’, π£ ∈ πΈ (in sorted order) do
ππ’ = U.find(π’); ππ£ = U.find(π£)
if ππ’ ≠ ππ£ then
π΄ = π΄∪ π
U.union(ππ’ ,ππ£ )
Fabian Kuhn
Informatik II, SS 2016
7
Kruskal: Laufzeitanalyse
Beste Union-Find Datenstruktur
• Laufzeit für π Union-Find-Operationen auf π Elementen
(π makeSet-Operationen):
πΆ π ⋅ πΆ π, π
• πΌ π, π ist die Inverse der Ackermannfunktion und wächst extrem
langsam (für alle halbwegs vernünftigen π, π, πΌ π, π ≤ 5)
Laufzeit Kruskal
• Kanten sortieren: π π ⋅ log π
• Union-Find-Operationen: π π ⋅ πΌ π, π
• Insgesamt: π π ⋅ log π
– besser, falls Kantengewichte schneller sortiert werden können
Fabian Kuhn
Informatik II, SS 2016
8
Prims MST Algorithmus
• Sollte man wohl eigentlich Jarvíks Algorithmus nennen
– wurde 1957 von Prim und bereits 1930 von Jarvík publiziert
• Eine zweite Implementierung des Basis-Algorithmus
π΄ = ∅
while π΄ ist kein Spannbaum do
Finde sichere Kante π’, π£ für π΄
π΄ = π΄ ∪ π’, π£
return π΄
• Idee: π΄ ist immer ein zusammenhängender Teilbaum
– Starte bei einem beliebigen Knoten π ∈ π
– Baum wächst von π aus, indem immer eine leichte Schnittkante des durch π΄
induzierten Schnitts hinzugefügt wird.
Fabian Kuhn
Informatik II, SS 2016
9
Sichere Kanten
Annahmen:
• πΊ = π, πΈ, π€ ist zus.-h., unger. Graph mit Kantengewichten π€ π
• π΄ ist Teilmenge (Teilgraph) eines MST
Theorem: Sei π, π β π ein Schnitt, so dass π΄ keine Schnittkanten
enthält und sei π’, π£ , π’ ∈ π, π£ ∈ π β π eine leichte Schnittkante
bezüglich π, π β π . Dann ist π’, π£ eine sichere Kante für π΄.
1
1
2
15
3
9
3
3
7
8
4
2
6
6
1
5
8
Fabian Kuhn
6
9
7
Informatik II, SS 2016
10
Prims MST-Algorithmus
π΄ = ∅
while π΄ ist
π = π’, π£
so dass
π΄ = π΄∪
kein Spannbaum do
ist Kante mit kleinstem Gewicht,
π’ ∈ π΄ und π£ ∉ π΄
π’, π£
• Wir müssen zeigen, dass π eine sichere Kante für π΄ ist
Fabian Kuhn
Informatik II, SS 2016
11
Prims MST-Algorithmus: Beispiel
1
3
13
6
10
23
4
14
21
2
7
28
31
16
17
9
19
25
12
8
20
18
Fabian Kuhn
11
Informatik II, SS 2016
12
Implementierung von Prims Algorithmus
• Knoten, welche im Teilbaum π΄ sind, heissen markiert
• Knoten π’:
– πΌ π’ ist der nächste Nachbar von π’ im durch π΄ bestimmten Teilbaum
– π π’ = dist π’, πΌ π’
(oder ∞ falls πΌ π’ = NULL)
for all π’ ∈ π β π do
π’.marked = false; π(π’) = ∞; πΌ π’ = NULL
π π = 0; π΄ = ∅
// Wir starten bei Knoten π
while there are unmarked nodes do
π’ = unmarked node with minimal π π’
for all unmarked neighbors π£ of π’ do
if π€ π’, π£ < π(π£) then
πΌ(π£) = π’; π π£ = π€ π’, π£
π’.marked = true
if π’ ≠ π then π΄ = π΄ ∪ π’, πΌ(π’)
Fabian Kuhn
Informatik II, SS 2016
13
Prioritätswarteschlange
Heap / Priority Queue:
• Verwaltet eine Menge von (key,value)-Paaren
Operationen:
• create
• H.insert(x, key)
• H.getMin()
• H.deleteMin()
: erzeugt einen leeren Heap
: fügt Element x mit Schlüssel key ein
: gibt Element mit kleinstem Schlüssel zurück
: löscht Element mit kleinstem Schlüssel
(gibt Element mit kleinstem Schlüssel zurück)
• H.decreaseKey(x, newkey) : Falls newkey kleiner als der aktuelle
Schlüssel von x ist, wird der Schlüssel
von x auf newkey gesetzt
Fabian Kuhn
Informatik II, SS 2016
14
Implementierung von Prims Algorithmus
for all π’ ∈ π β {π } do
π’.marked = false; π(π’) = ∞; πΌ π’ = NULL
π π = 0; π΄ = ∅
// Wir starten bei Knoten π
while there are unmarked nodes do
π’ = unmarked node with minimal π π’
for all unmarked neighbors π£ of π’ do
if π€ π’, π£ < π(π£) then
πΌ(π£) = π’; π π£ = π€ π’, π£
π’.marked = true
if π’ ≠ π then π΄ = π΄ ∪ π’, πΌ(π’)
Fabian Kuhn
Informatik II, SS 2016
15
Implementierung von Prims Algorithmus
π» = new priority queue; π΄ = ∅
for all π’ ∈ π β {π } do
π».insert(π’, ∞); πΌ(π’) = NULL
π».insert(π , 0)
while π» is not empty do
π’ = H.deleteMin()
for all unmarked neighbors π£ of π’ do
if π€ π’, π£ < π(π£) then
π».decreaseKey(π£, π€ π’, π£ )
πΌ π£ = π’
if π’ ≠ π then π΄ = π΄ ∪ π’, πΌ π’
Fabian Kuhn
Informatik II, SS 2016
16
Analyse von Prims MST-Algorithmus
Anzahl Priority Queue Operationen
• create
• insert
• getMin / deleteMin
• decreaseKey
Gesamt-Laufzeit
Fabian Kuhn
Informatik II, SS 2016
17
Prioritätswarteschlangen
Implementierung als Binärbaum mit Min-Heap Eigenschaft
• Die Datenstruktur heisst deshalb oft auch Heap
• Ein Baum hat die Min-Heap Eigenschaft, falls in jedem Teilbaum,
die Wurzel den kleinsten Schlüssel hat
• getMin-Operation: trivial!
• Baum wird immer so balanciert, wie möglich gehalten
Fabian Kuhn
Informatik II, SS 2016
18
Prioritätswarteschlangen: Einfügen
3
10
13
12
17
Fabian Kuhn
7
23
9
14
Informatik II, SS 2016
19
Prioritätswarteschlangen: Delete-Min
3
10
7
13
11
17
Fabian Kuhn
14
23
9
16
Informatik II, SS 2016
20
Prioritätswarteschlangen: Decrease-Key
3
10
7
13
11
17
Fabian Kuhn
14
16
23
17
9
24
Informatik II, SS 2016
21
Prioritätswarteschlangen: Analyse
• Die besprochene Variante heisse auch binärer Heap
– durch einen Binärbaum mit Min-Heap-Eigenschaft implementiert
• Tiefe des Baums ist immer genau π₯π¨π π π
• Laufzeit aller Operationen: πΆ π₯π¨π π
– wenn man den Binärbaum irgendwie vernünftig implementiert
– man muss immer höchsten einmal den Binärbaum hoch (bei insert,
decreaseKey) oder runter (bei deleteMin)
– Wir werden gleich eine elegante Art sehen, den binären Heap zu impl.
Fabian Kuhn
Informatik II, SS 2016
22
Binäre Heaps, Array-Implementierung
Idee: Speichere alles in ein Array
• Das geht, weil der Baum perfekt balanciert ist
3
10
7
13
11
17
Fabian Kuhn
14
16
23
17
9
24
Informatik II, SS 2016
23
Binäre Heaps, Array-Implementierung
Positionen im Array (bei π Elementen):
• Wurzel: 1, letzter Eintrag: π, Parent von π: π Τ2
• linkes Kind von π: 2π, rechtes Kind von π: 2π + 1
Pseudocode am Beispiel von Insert
• Elemente sind in Array π΄ and Positionen 1, … , π gespeichert
insert(x):
n = n + 1
A[n] = x
i = n
while (i > 1) and (A[i] < A[i/2]) do
swap(A[i], A[i/2])
i = i/2
Fabian Kuhn
Informatik II, SS 2016
24
Binäre Heaps: Pseudocode Delete-Min
smallest(i): // returns index of smallest key among π and children
j = i
if (2*i <= n) and (A[2*i] < A[i]) then
j = 2*i
if (2*i+1 <= n) and (A[2*i+1] < A[j]) then
j = 2*i + 1
return j
deleteMin():
minItem = A[1]
A[1] = A[n]; n = n – 1;
i = 1; j = smallest(i)
while j ≠ i do
swap(A[i], A[j])
i = j
j = smallest(i)
return minItem
Fabian Kuhn
Informatik II, SS 2016
25
Binäre Heaps: Pseudocode Decrease-Key
decreaseKey(i, x):
while (i > 1) and (A[i] < A[i/2]) do
swap(A[i], A[i/2])
i = i/2
Fabian Kuhn
Informatik II, SS 2016
26
Heapsort
• Die Array-Implementierung von Heaps (Prioritätswarteschlangen)
gibt auch einen weiteren effizienten Sortieralgorithmus
Heapsort (π― ist ein binärer Heap, sortiere Array π¨)
H = new BinaryHeap()
for i = 0 to n – 1 do
H.insert(A[i])
for i = 0 to n – 1 do
A[i] = H.deleteMin()
• Laufzeit: πΆ π π₯π¨π π
Fabian Kuhn
Informatik II, SS 2016
27
Prims Algorithmus mit binären Heaps
π» = new BinaryHeap(); π΄ = ∅
for all π’ ∈ π β {π } do
π».insert(π’, ∞); πΌ(π’) = NULL
π».insert(π , 0)
while π» is not empty do
π’ = H.deleteMin()
for all neighbors π£ of π’ do
if π€ π’, π£ < π(π£) then
π».decreaseKey(π£, π€ π’, π£ ); πΌ π£ = π’
if π’ ≠ π then π΄ = π΄ ∪ π’, πΌ π’
Laufzeit: πΆ π ⋅ π₯π¨π π
• π ≤ π + 1 insert-Operationen und deleteMin-Operationen
• ≤ π decreaseKey-Operationen
Fabian Kuhn
Informatik II, SS 2016
28
Prims Algorithmus: Bessere Laufzeit
Laufzeit mit binären Heaps: πΆ π ⋅ π₯π¨π π
• π ≤ π + 1 insert-Operationen und deleteMin-Operationen
• ≤ π decreaseKey-Operationen
Beste Implementierung von Prioritätswarteschlangen:
• Fibonacci Heaps (siehe Vorlesung Algorithmentheorie)
• Laufzeit der Operationen (deleteMin, decreaseKey amortisiert)
insert: πΆ π , deleteMin: πΆ π₯π¨π π , decreaseKey: πΆ π
Laufzeit mit Fibonacci Heaps: πΆ π + π ⋅ π₯π¨π π
• π ≤ π + 1 insert-Operationen und deleteMin-Operationen
• ≤ π decreaseKey-Operationen
Fabian Kuhn
Informatik II, SS 2016
29
Kürzeste Wege
Problem
• Gegeben: gewichteter Graph πΊ = π, πΈ, π€ , Startknoten π ∈ π
– Wir bezeichnen Gewicht einer Kante π’, π£ als π€ π’, π£
– Annahme: ∀π ∈ πΈ: π€ π ≥ 0
• Ziel: Finde kürzeste Pfade / Distanzen von π zu allen Knoten
– Distanz von π zu π£: ππΊ π , π£
1
1
2
3
9
3
(Länge eines kürzesten Pfades)
15
3
7
8
4
2
6
1
6
5
8
Fabian Kuhn
6
9
7
Informatik II, SS 2016
30