Upload
adalheidis-rehagen
View
110
Download
2
Embed Size (px)
Citation preview
WS 2006-07
Algorithmentheorie
15 – Fibonacci-Heaps
Tobias Lauer
2 WS 2006-07
Vorrangswarteschlangen Implementationen
Liste Heap Bin. – Q. Fib.-Hp.
insert O(1) O(log n) O(log n) O(1)
min O(n) O(1) O(log n) O(1)
delete-min
O(n) O(log n) O(log n) O(log n)*
meld (mn)
O(1)O(n) od.
O(m log n)O(log n) O(1)
decr.-key O(1) O(log n) O(log n)O(1)*
* = amortisierte KostenQ.delete(e) = Q.decreasekey(e, - ) + Q.deletemin()
3 WS 2006-07
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
2 19
13 45 8
36 21
24
15 83 52
79
117
4 WS 2006-07
Erweiterte Child-Sibling Darstellung
Knotenformat: parent
entry degree
child mark
left right
2 19
13 45 8
36 21
24
15 83 52
79
117
min
5 WS 2006-07
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)
6 WS 2006-07
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.
2
13 8
36 21
24
83 52
2
13 8
36 21
24
83 52
7 WS 2006-07
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 }
8 WS 2006-07
Fibonacci-Heaps: Operationen
Q.initialize:
Q.root = null
Q.insert(e):
F = new F-Heap(e)
Q.meld(F)
Zeit = O(1)
9 WS 2006-07
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: ?
10 WS 2006-07
deletemin: Beispiel
2 19
13 45 8
36 21
24
15 83 52
79
117
11 WS 2006-07
deletemin: Beispiel
19
24
83 52
79
117 13 45 8
36 2115
12 WS 2006-07
deletemin: Beispiel
19
24
83 52
79
117
1345 8
36 2115
13 WS 2006-07
consolidate: Beispiel
1913 45 8
36 21 2415
83 52
117
0 1 2 3 4 5Rang-Array:
14 WS 2006-07
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
15 WS 2006-07
consolidate: Beispiel
1913 45 8
36 21 2415
83 52
117
0 1 2 3 4 5Rang-Array:
16 WS 2006-07
consolidate: Beispiel
1913 45 8
36 21 2415
83 52
117
0 1 2 3 4 5Rang-Array:
17 WS 2006-07
consolidate: Beispiel
19
13 45 8
36 21
24
15
83 52
117
0 1 2 3 4 5Rang-Array:
18 WS 2006-07
consolidate: Beispiel
19
13
45 8
36 21
24
15
83 52
117
0 1 2 3 4 5Rang-Array:
19 WS 2006-07
consolidate: Beispiel
19
13 45
8
36 21
24
15
83 52
117
0 1 2 3 4 5Rang-Array:
20 WS 2006-07
consolidate: Beispiel
19
13 45
8
36 21
24
15
83 52
117
21 WS 2006-07
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}
22 WS 2006-07
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
23 WS 2006-07
Kosten von deletemin
Vorläufig:
O(maxRank(n)) + O(#links)
24 WS 2006-07
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).
25 WS 2006-07
Beispiel für decreasekey
6 5
13 45 8
36 21
24
15 83 52
117
64
64
Setze den Schlüssel 64 auf 14 herab.
26 WS 2006-07
Beispiel für decreasekey
6 5
13 45 8
36 21
24
15 83 52
117
64
14
27 WS 2006-07
Beispiel für decreasekey
6 5
13 45 8
36 21
24
15 83 52
117
64
14
28 WS 2006-07
Beispiel für decreasekey
6 5
13 45 8
36
21
24
15 83 52
117
64
14
29 WS 2006-07
Beispiel für decreasekey
6 5
13 45 8
36
21
24
15 83 52
117
64
14
30 WS 2006-07
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.
31 WS 2006-07
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 + 2∙mi mit wi = Zahl der Wurzelknotenund mi = Zahl der markierten Knoten (die nicht Wurzeln sind)
Beispiel: inserttatsächliche Kosten: ci = O(1)Potential erhöht sich um 1, also Фi – Фi-1 = 1ai = ci + 1
32 WS 2006-07