Prioritätslisten, Implementierung mit Binary Heaps
Transcription
Prioritätslisten, Implementierung mit Binary Heaps
Einfügen h: a c g r d p h w t s z q j: 1 2 3 4 5 6 7 8 9 10 11 12 13 Procedure insert(e : Element ) assert n < w n++ ; h[n]:= e siftUp(n ) Procedure siftUp(i : N) assert the heap property holds except maybe at position i if i = 1 ∨ h[bi /2c] ≤ h[i ] then return swap(h [i ], h [bi /2c]) siftUp(bi /2c) a c g r d p h a c b w t s z q r d g h insertb w t s z q p 231 Function deleteMin : Element h[1] : Element h[1]:= h[n]; n−− result= siftDown(1) return result compare swap 1 3 4 1 6 9 8 7 3 7 4 1 6 9 8 3 7 4 1 6 9 8 3 4 7 6 9 8 232 Function deleteMin compare swap : Element h[1] : Element h[1]:= h[n]; n−− result= siftDown(1) 1 3 1 6 7 3 1 6 3 7 1 6 3 4 6 4 9 8 7 4 9 8 4 9 8 7 9 8 return result Procedure siftDown(i : N) assert heap property except, possibly at j = 2i and j = 2i + 1 if 2i ≤ n then // i is not a leaf if 2i + 1 > n ∨ h[2i ] ≤ h[2i + 1] then m:= 2i else m:= 2i + 1 assert 6 ∃sibling(m) ∨ h[sibling(m)] ≥ h[m] if h[i ] > h[m] then // heap property violated swap( h[i ], h[m]) m) siftDown( assert the heap property holds for the subtree rooted at i 233 deleteMin: Beispiel 1 2 3 4 5 6 7 8 9 10 11 12 13 a c g deleteMin r d p h c d g w t s z q r q p h w t s z 234 Binärer Heap Analyse I I I I I Satz: min dauert O(1). Lemma: Höhe ist blog nc Satz: insert dauert O(log n). Satz: deleteMin dauert O(log n). Beweis: Zeit O(1) pro Schicht. 235 Binärer Heap Konstruktion Procedure buildHeapBackwards for i := bn/2c downto 1 do i) siftDown( 236 Beispiel: Binärer Heap Konstruktion 9 6 4 31 8 7 compare swap 9 9 6 1 3 1 4 38 7 4 68 7 1 3 4 68 7 9 237 Binärer Heap Konstruktion I I Satz: buildHeap läuft in Zeit O(n) Beweis: Sei k = blog nc. In Tiefe ` I 2 ` ∈ 0.. blog nc: Aufrufe von siftDown I Kosten je O(k − `). Insgesamt: ! O ∑ 0≤`<k 2 ` (k − `) =O 2k ∑ 0≤`<k k −` 2k −` ! = O 2k j ! ∑ j j ≥1 2 | {z } O(1)! =O 2k = O(n) 238 Ein nützlicher Rechentrick ∑ j · 2−j = ∑ 2−j + ∑ 2−j + ∑ 2−j + . . . 1/2 + j ≥1 j ≥1 j ≥2 j ≥3 = (1 + 1/2 + 1/4 + 1/8 + . . .) · ∑ 2−j j ≥1 = 2·1 = 2 1/4 + 1/4 + 1/8 + 1/8 + 1/8 + 1/16 + ... = 1 1/16 + ... = 1/2 1/16 + ... = 1/4 1/16 + ... = 1/8 ... = ... ____________________________________________ 1*1/2 + 2*1/4 + 3*1/8 + 4*1/16 + ... = 2 239 Heapsort Procedure heapSortDecreasing( buildHeap( a) for i := n downto 2 h[i ]:= deleteMin Laufzeit: a[1..n]) do O(n log n) Andere Sichtweise: eziente Implementierung von Sortieren durch Auswahl Frage: Wie sortiert man aufsteigend? 240 Heapsort: Beispiel compare swap 9 3 1 3 7 3 7 4 8 7 4 68 9 4 68 1 9 68 1 4 8 6 6 7 6 7 8 7 9 8 31 9 431 9 431 7 9 8 8 9 8 9 6431 76431 76431 4 7 31 9 6 9 8 7 6431 9 876431 241 Heapsort ↔ Quicksort ↔ Mergesort Heapsort Vergleiche E[Vergleiche] zusätzl. Platz Cachezugrie B =Blockgröÿe) ( O(n log n) O(n log n) O(1) O(n log n) Quicksort O n2 O(n log n) O(log n) O Bn log n Mergesort O(n log n) O(n log n) O(n) O Bn log n Kompromiss: z. B. introspektives Quicksort der C++ Standardbibliothek: Quicksort starten. Zu wenig Fortschritt? Umschalten auf Heapsort. 242 Adressierbare Prioritätslisten Procedure build({e1 , . . . , en }) M := {e1 , . . . , en } Function size return |M | Procedure insert(e ) M := M ∪ {e } Function min return min M Function deleteMin e := min M ; M := M \ {e }; return e Function remove(h : Handle) e := h; M := M \ {e }; return e Procedure decreaseKey(h : Handle, k : Key) assert key(h) ≥ k ; key(h):= k Procedure merge(M 0 ) M := M ∪ M 0 243 Adressierbare Prioritätslisten: Anwendungen Greedy-Algorithmus: while solution not complete do add the best available piece to the solution update piece priorities // e.g., using addressable priority queue Beispiele: I Dijkstras Algorithmus für kürzeste Wege I Jarník-Prim Algorithmus für minimale Spannbäume I Scheduling: Jobs → am wenigsten belastete Maschine I Hierarchiekonstruktion für Routenplanung I Suche nach erfüllenden Belegungen aussagenlog. Formeln? 244 Adressierbare Binäre Heaps 1 3 Problem: Elemente bewegen sich. 4 Dadurch werden Elementverweise ungültig. 7 68 9 Ausweg: Unbewegliche Vermittler-Objekte. Invariante: proxy(e ) verweist auf Position von e . (Ein) Vermittler bei jeder Vertauschung aktualisieren. Rückverweis Element → 1 Vermittler 3 4 7 6 Laufzeit: O(log n) für alle Operationen ausser merge und buildHeap, die 8 9 O(n) brauchen. 245 Adressierbare Prioritätslisten Laufzeiten Operation build size min insert deleteMin remove decreaseKey merge Binary Heap Fibonacci Heap (Buch) O(n) O(1) O(1) O(log n) O(log n) O(log n) O(log n) O(n) O(n) O(1) O(1) O(1) O(log n) O(log n) O(1) am. O(1) 246 Prioritätslisten: Mehr I Untere Schranke Ω (log n) für deleteMin, vergleichsbasiert. Übung I ganzzahlige Schlüssel (stay tuned) I extern: Geht gut (nichtaddressierbar) I parallel: Semantik? 247 Prioritätslisten: Zusammenfassung I Häug benötigte Datenstruktur I Addressierbarkeit ist nicht selbstverständlich I Binäre Heaps sind einfache, relativ eziente Implementierung 248 Was haben wir jenseits von Prioritätslisten gelernt? I implizites Layout von Binärbäumen I ∑j j 2j I Heapsort (inplace!) 249