1 vorlesung informatik 2 algorithmen und datenstrukturen (17 – fibonacci-heaps – analyse) tobias...
Post on 05-Apr-2015
110 Views
Preview:
TRANSCRIPT
1
Vorlesung Informatik 2
Algorithmen und Datenstrukturen
(17 – Fibonacci-Heaps – Analyse)
Tobias Lauer
2
Vorrangswarteschlangen: Operationen
Operationen einer Vorrangswarteschlange (Priority Queue) Q:
Q.insert(int k): Füge einen neuen Knoten mit Schlüssel (= Priorität) k ein.
Q.accessmin(): Gib den Knoten mit niedrigstem Schlüssel (= der höchsten Priorität) zurück.
Q.deletemin(): Entferne den Knoten mit dem niedrigsten Schlüssel.
Q.decreasekey(Node N, int k): Setze den Schlüssel von Knoten N auf den Wert k herab.
Q.delete(Node N): Entferne den Knoten N.
Q.meld(PriorityQueue P): Vereinige Q mit der Vorrangswarteschlange P.
Q.isEmpty(): Gibt an, ob Q leer ist.
Bemerkung: Die effiziente Suche nach einem bestimmten Element oder Schlüssel wird in
Vorrangswarteschlangen nicht unterstützt! Für decreasekey und delete muss man das
entsprechende Element also bereits kennen bzw. Zugriff darauf haben.
3
Fibonacci-Heaps: Idee
• Liste von Bäumen (beliebigen Verzweigungsgrades), die alle heapgeordnet sind.
Definition:
Ein Baum heißt (min-)heapgeordnet, wenn der Schlüssel jedes Knotens größer
oder gleich dem Schlüssel seines Vaterknotens ist (sofern er einen Vater hat).
• Die Wurzeln der Bäume sind in einer doppelt verketteten, zirkulären Liste
miteinander verbunden (Wurzelliste).
• Der Einstiegspunkt ist ein Zeiger auf den Knoten mit minimalem Schlüssel.
2 19
13 45 8
36 21
24
15 83 52
79
117
4
Laufzeitanalyse
Laufzeit von deletemin():
remove: O(1)
consolidate: O(#links) + O(maxRank(n))
updatemin: #Wurzelknoten nach consolidate = O(maxRank(n))
Gesamtkosten: O(#links) + O(maxRank(n))
Nach dem Konsolidieren gibt es nur noch Wurzelknoten mit unterschiedlichem Rang.
Definiere maxRank(n) als den höchstmöglichen Rang, den ein Knoten in einem
Fibonacci-Heap der Größe n haben kann. (Berechnung von maxRank(n) später.)
5
Laufzeitanalyse
Laufzeit von decreasekey():
Schlüssel neu setzen: O(1)
cut: O(1)
Cascading cuts: #cuts · O(1)
Markieren: O(1)
Gesamtkosten: O(#cuts)
6
Laufzeitanalyse
Laufzeit von delete():
• Falls der entfernte Knoten der Minimalknoten ist, sind die Kosten gleich wie bei
deletemin: O(#links) + O(maxRank(n))
• Ansonsten sind sie ähnlich wie bei decreasekey:
cut: O(1)
Cascading cuts: #cuts · O(1)
Markieren: O(1)
remove: O(1)
Gesamtkosten: O(#cuts)
7
Analyse
Beobachtungen:
Bei deletemin beeinflusst die Zahl der link-Operationen die tatsächliche Laufzeit.
Bei decreasekey (und delete) ist es die Zahl der cascading cuts.
In beiden Fällen bekommen wir im schlimmsten Fall eine lineare Laufzeit:
Aber: Wie häufig kann das passieren?
5 8 217 2
28
11
5
8
Amortisierte Analyse
Beobachtungen:
Bei deletemin beeinflusst die Zahl der link-Operationen die tatsächliche Laufzeit.
Bei decreasekey (und delete) ist es die Zahl der „cascading cuts“.
Idee: Spare dafür Guthaben an (Bankkonto-Paradigma)!
Annahme: Die Kosten pro link und pro cut seien jeweils 1€.
(1) Sorge dafür, dass für jeden Wurzelknoten immer 1€ Guthaben vorhanden ist,
mit dem sich die link-Operation bezahlen lässt, wenn dieser Knoten an einen
anderen angehängt wird.
(2) Sorge dafür, dass für jeden markierten Knoten immer 2€ Guthaben
vorhanden sind. Damit kann man bei „cascading cuts“ das Abtrennen (cut)
dieses Knotens bezahlen und hat noch 1€ übrig für (1).
9
Beispiel
913 45 3
36 21 24
75
52
79
107
1147
36
3214
50 39
61
10
Guthaben ansparen
Bei welchen Operationen müssen wir etwas dazu bezahlen, um das Guthaben
anzusparen?
Neue Wurzelknoten können entstehen bei:
– insert: gib dem neu eingefügten Wurzelknoten noch 1€ dazu.
– decreasekey: bezahle 1€ für den abgetrennten Knoten dazu.
– deletemin und delete: bezahle bei remove für jeden Sohn des entfernten
Knotens 1€ dazu, insgesamt also bis zu maxRank(n) €.
Markierte Knoten können nur am Ende von decreasekey und delete entstehen:
– Bezahle beim Markieren zusätzlich 2€ für den markierten Knoten.
11
Amortisierte Kosten von insert
Erstellen des Knotens: O(1)
Einfügen in Wurzelliste: O(1) + O(1)
Amortisierte Gesamtkosten: O(1)
12
Amortisierte Kosten von deletemin
remove: O(1) + O(maxRank(n))
Erstellen des Rang-Arrays: O(maxRank(n))
link-Operationen: #links · O(1) wird vom Guthaben bezahlt!
Restl. Kosten consolidate: O(maxRank(n))
Update Minimum-Zeiger: O(maxRank(n))
Amortisierte Gesamtkosten: O(maxRank(n))
13
Beispiel
913 45 3
36 21 24
75
52
79
107
1147
36
3214
50 39
61
14
Beispiel
913 45 36 21
24
75
52
79
107
1147
36
3214
50 39
61
remove: Bezahle zusätzlich für jeden Sohn 1€:
15
Beispiel
913 45
36
21
24
75
52
79
107
1147
36
3214
50 39
61
link: Bezahle alle Kosten mit dem Guthaben.
16
Beispiel
913 45
36
2124
75
52
79
107
1147
36
3214
50 39
61
link: Bezahle alle Kosten mit dem Guthaben.
17
Beispiel
913
45
36
2124
75
52
79
107
1147
36
3214
50 39
61
link: Bezahle alle Kosten mit dem Guthaben.
18
Beispiel
9
1345
36
2124
75
52
79
107
1147
36 3214
50 39
61
link: Bezahle alle Kosten mit dem Guthaben.
19
Beispiel
9
13
45
36
21
24
75
52
79
10
7
1147
36
3214
50 39
61
link: Bezahle alle Kosten mit dem Guthaben.
20
Amortisierte Kosten von decreasekey
Schlüsselwert neu setzen: O(1)
cut: O(1) + O(1)
Cascading cuts: #cuts · O(1) wird vom Guthaben bezahlt!
Markieren: O(1) + 2 · O(1)
Amortisierte Gesamtkosten: O(1)
21
Beispiel
913 45 3
36 21 24
75
52
79
7
1147
36
3214
50 39
22
Beispiel
913 45 3
36 21 24
20
52
79
7
1147
36
3214
50 39
Bezahle für den ersten cut noch 1€ zusätzlich:
23
Beispiel
913 45 3
36 21 24
20
52
79
7
1147
36
3214
50 39
Bezahle für den ersten cut noch 1€ zusätzlich:
24
Beispiel
913 45 3
36 21 24
20
52
79
7
1147
36
3214
50 39
Alle weiteren cascading cuts werden komplett vom Guthaben bezahlt:
25
Beispiel
913 45 3
36 21 24
20
52
79
7
1147
36
3214
50
39
Alle weiteren cascading cuts werden vom Guthaben bezahlt:
26
Beispiel
913 45 3
36 21 24
20
52
79
7
1147
36
3214
50
39
Beim Markieren bezahle noch 2€ extra:
27
Amortisierte Kosten von delete
• Falls der entfernte Knoten der Minimalknoten ist, sind die Kosten diejenigen von
deletemin: O(maxRank(n))
• Ansonsten:
cut: O(1)
Cascading cuts: #cuts · O(1) wird vom Guthaben bezahlt!
Markieren: O(1) + 2 · O(1)
remove: O(1) + O(maxRank(n))
Amortisierte Gesamtkosten: O(maxRank(n))
28
Amortisierte Analyse
Amortisierte Kosten
• Insert: O(1)
• Accessmin: O(1)
• Deletemin: O(maxRank(n))
• Decreasekey: O(1)
• Delete: O(maxRank(n))
• Meld: O(1)
Noch zu zeigen: maxRank(n) = O(log n). D.h. der maximale Rang eines Knotens in
einem Fibonacci-Heap ist logarithmisch in der Größe n des Fibonacci-Heaps.
29
Berechnung von maxRank(n)
Lemma 1: (Mindestrang von Söhnen)
Sei N ein Knoten in einem Fibonacci-Heap und k = N.rank. Betrachte die Söhne
C1, ..., Ck von N in der Reihenfolge, in der sie (mit link) zu N hinzugefügt wurden.
Dann gilt:
(1) C1.rank ≥ 0
(2) Ci.rank ≥ i - 2 für i = 2, ..., k
Beweis: (1) klar
(2) Als Ci zum Sohn von N wurde, waren C1, ..., Ci-1 schon Söhne von N,
d.h. es war N.rank ≥ i-1. Da durch link immer Knoten mit gleichem Rang
verbunden werden, war beim Einfügen also auch Ci.rank ≥ i-1. Seither kann
Ci höchstens einen Sohn verloren haben (wegen cascading cuts), daher
muss gelten: Ci.rank ≥ i - 2
30
Berechnung von maxRank(n)
Lemma 2: (Mindestzahl von Nachkommen)
Sei N ein Knoten in einem Fibonacci-Heap und k = N.rank.
Sei size(N) = die Zahl der Knoten im Teilbaum mit Wurzel N.
Dann gilt: size(N) ≥ Fk+2 ≥ 1.618k
D.h. ein Knoten mit k Söhnen hat mind. Fk+2 Nachkommen (inkl. sich selbst).
Beweis: Sei Sk = min {size(N) | N mit N.rank = k}, d.h. die kleinstmögliche Größe
eines Baums mit Wurzelrang k. (Klar: S0 = 1 und S1 = 2.)
Seien wieder C1, ..., Ck die Söhne von N in der Reihenfolge, in der sie zu N
hinzugefügt wurden.
31
Berechnung von maxRank(n)
Beweis: Sei S(k) = min {size(N) | N mit N.rank = k}, d.h. die kleinstmögliche Größe eines
Baums mit Wurzelrang k. (Klar: S(0) = 1 und S(1) = 2.)
Seien wieder C1, ..., Ck die Söhne von N in der Reihenfolge, in der sie zu N hinzugefügt
wurden.
Es ist size(N) ≥
13
36
21
10
3214
61
k
i
k
iS
kSS
rankCSrankCSrankCSkS
2
21
)2(2
)2(...)22(11
).(...).().(1)(
32
Berechnung von maxRank(n)
• Es ist size(N) S(k) =
k
i
iS2
)2(2
33
Berechnung von maxRank(n)
Satz: (maximaler Rang eines Knotens)
Der maximale Rang maxRank(n) eines beliebigen Knotens in einem
Fibonacci-Heap mit n Knoten ist beschränkt durch O(log n).
Beweis: Sei N ein Knoten eines Fibonacci-Heaps mit n Knoten und sei k = N.rank.
Es ist n ≥ size(N) ≥ 1.618k (nach Lemma 2)
Daher istk ≤ log1.618(n) = O(log n)
34
Zusammenfassung
Lineare Liste (Min-)Heap Fibonacci-Heap
insert: O(1) O(log n) O(1)
accessmin: O(1) O(1) O(1)
deletemin: O(n) O(log n) O(log n)*
decreasekey: O(1) O(log n) O(1)*
delete: O(n) O(log n) O(log n)*
meld: O(1) O(m log(n+m)) O(1)
*Amortisierte Kosten
top related