WS Algorithmentheorie 15 – Fibonacci-Heaps Tobias Lauer
2WS Vorrangswarteschlangen Implementationen ListeHeapBin. – Q.Fib.-Hp. insertO(1)O(log n) O(1) minO(n)O(1)O(log n)O(1) delete- min O(n)O(log n) O(log n)* meld (m n) O(1) O(n) od. O(m log n) O(log n)O(1) decr.-keyO(1)O(log n) O(1)* * = amortisierte Kosten Q.delete(e) = Q.decreasekey(e, - ) + Q.deletemin()
3WS Fibonacci-Heaps als lazy Binomial Queues Verschmelze Bäume nur dann, wenn ohnehin alle Wurzeln betrachtet werden müssen Lasse auch Bäume zu, die keine Binomialbäume sind
4WS Erweiterte Child-Sibling Darstellung Knotenformat: parent entrydegree childmark leftright min
5WS Vorteile der zusätzlichen Zeiger Zugriff auf Minimum (accessmin) jederzeit in O(1) (allerdings muss der min-Zeiger immer aktuell gehalten werden) Verketten von (und damit auch das Einfügen in) zirkulären Listen ist in O(1) möglich Entfernen aus doppelt verketteten Listen ebenfalls in O(1)
6WS Fibonacci-Bäume: Vereinigung (Link) Vereinigung zweier Bäume B, B´ von gleicher Ordnung (degree) k Link-Operation: Ausführbar in konstanter Zeit: O(1) Resultierender Baum hat Grad k+1 Unterschied zu Binomial Queues: Ursprungsbäume müssen nicht dieselbe Gestalt haben
7WS Verschmelzen zweier F-Heaps (meld) Hänge die Wurzellisten der beiden F-Heaps aneinander. Aktualisiere den min-Zeiger, so dass er auf den kleineren der beiden Minimalknoten zeigt Q.meld(F-Heap F): 1 Q.min.right.left = F.min.left 2 F.min.left.right = Q.min.right 3 Q.min.right = F.min 4 F.min.left = Q.min 5 Q.min = min { F.min, Q.min }
8WS Fibonacci-Heaps: Operationen Q.initialize: Q.root = null Q.insert(e): F = new F-Heap(e) Q.meld(F) Zeit = O(1)
9WS Fibonacci-Heaps: Deletemin Q.deletemin(): 1. Entferne den min-Knoten und hänge stattdessen die Lister seiner Söhne in die Wurzelliste ein. 2. Gehe die Wurzelliste durch: (a) bestimme den neuen Minimalknoten (b) konsolidiere dabei die Liste, d.h. verbinde Bäume mit gleichem Wurzelgrad (link) Zeit: ?
10WS deletemin: Beispiel
WS deletemin: Beispiel
12WS deletemin: Beispiel
13WS consolidate: Beispiel Rang-Array:
14WS Kosten von deletemin Das eigentliche Entfernen geht in O(1) Kosten hängen im Wesentlichen vom Konsolidierungsprozess ab, d.h. von der Länger der Wurzelliste und der Anzahl der notwendigen link-Operationen Wie lässt sich das Konsolidieren effizient bewerkstelligen? Beobachtungen: Jeder Wurzelknoten muss mindestens einmal betrachtet werden Am Ende darf es für jeden möglichen Rang höchstens einen Knoten geben
15WS consolidate: Beispiel Rang-Array:
16WS consolidate: Beispiel Rang-Array:
17WS consolidate: Beispiel Rang-Array:
18WS consolidate: Beispiel Rang-Array:
19WS consolidate: Beispiel Rang-Array:
20WS consolidate: Beispiel
21WS Analyse von consolidate rankArray = new FibNode[maxRank(n)+1]; // Erstelle das Array for each FibNode N in rootlist { while (rankArray[N.rank] != null) { // Position besetzt N = link(N, rankArray[N.rank]); // Verbinde Bäume rankArray[N.rank-1] = null; // Lösche alte Pos. } rankArray[N.rank] = N; // Eintragen in Array }
22WS Analyse for each FibNode N in rootlist { while (rankArray[N.rank] != null) { N = link(N, rankArray[N.rank]); rankArray[N.rank-1] = null; } rankArray[N.rank] = N; } Sei k = #Wurzelknoten vor dem Konsolidieren. Diese k Knoten lassen sich aufteilen in W ={Knoten, die am Ende noch in der Wurzelliste sind} L = {Knoten, die an einen anderen Knoten angehängt wurden} Es gilt:Kosten(for-Schleife) = Kosten(W) + Kosten(L) = |rankArray| + #links
23WS Kosten von deletemin Vorläufig: O(maxRank(n)) + O(#links)
24WS Fibonacci-Heaps: decreasekey Q.decreasekey(FibNode N, int k) : Setze den Schlüsselwert von N auf k herab. Wenn die Heap-Bedingung nicht mehr erfüllt ist ( k < N.parent.key ): Trenne N von seinem Vater ab (mit cut) und hänge ihn (rechts vom Minimalknoten) in die Wurzelliste ein Falls der Vater markiert ist ( N.parent.mark == true ), trenne auch ihn von seinem Vater ab; wenn auch dessen Vater markiert ist, trenne auch diesen ab usw. (cascading cuts) Markiere den Knoten, dessen Sohn zuletzt abgetrennt wurde (sofern dieser kein Wurzelknoten ist). Aktualisiere den Minimum-Zeiger (falls k < min.key ).
25WS Beispiel für decreasekey Setze den Schlüssel 64 auf 14 herab.
26WS Beispiel für decreasekey
27WS Beispiel für decreasekey
28WS Beispiel für decreasekey
29WS Beispiel für decreasekey
30WS Kosten von decreasekey Schlüssel neu setzen und Vergleich mit Vater: O(1) Abtrennen vom Vaterknoten und in Wurzelliste:O(1) Cascading cuts:#cuts Markieren des letzten Knotens:O(1) Kosten hängen von der Anzahl der cascading cuts ab.
31WS Amortisierte Analyse – Potentialmethode Ordne jedem Zustand der Datenstruktur einen Wert Ф (Potential) zu Die amortisierten Kosten ai der i-ten Operation sind definiert als ai = ci + (Фi – Фi-1) die tatsächlichen Kosten zuzüglich der Änderung des Potentials durch die i-te Operation. Definiere Фi = wi + 2mi mit wi = Zahl der Wurzelknoten und mi = Zahl der markierten Knoten (die nicht Wurzeln sind) Beispiel: insert tatsächliche Kosten: ci = O(1) Potential erhöht sich um 1, also Фi – Фi-1 = 1 ai = ci + 1
32WS