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