Fibonacci Heaps

Werbung
Priority Queues
Operationen:
z
Fibonacci Heaps
z
z
AK der Algorithmik 5, SS 2005
Hu Bin
z
Insert
ExtractMax
IncreaseKey
Anwendungen:
z
z
z
z
z
kürzeste Wege mit Dijkstra
Finden eines minimalen Schnittes
MST mit Prim
…
Binäre Heaps
Fibonacci
Heapeigenschaft: Vater größer als Kinder
z
z
z
z
z
insert: O(log n)
extractMax: O(log n)
increaseKey: O(log n)
„A certain man put a pair of rabbits in a place surrounded on all
sides by a wall. How many pairs of rabbits can be produced from
that pair in a year if it is supposed that every month each pair begets
a new pair which from the second month on becomes productive?“
12
8
3
4
6
2
5
Fibonacci Heaps
z
z
z
Max
8
8
ai+2 = ai+1 + ai
a1 = 1
a2 = 1
Y a = <1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 134, …>
z
Laufzeitvergleich
Menge von Bäumen, die die Heapeigenschaft
erfüllen
Globaler Max-Pointer
Jeder Knoten ist angeregt oder nicht
17
ca. 1170 – 1250, Pisa, Mathematiker
Berühmt wegen:
Operation
Binärer Heap
insert
Fibonacci Heap
O(log n)
O(1)*
extractMax
O(log n)
O(log n)*
increaseKey
O(log n)
O(1)*
* Amortisierte Analyse
26
18
5
3
12
Frage: Kann extractMax schneller gehen?
12
11
7
1
Fibonacci Heaps: insert
z
Fibonacci Heaps: insert
Max
insert(v):
17
(1) mache v zu neuer Wurzel
(2) setze v auf nicht aufgeregt
(3) gegebenenfalls Max-Pointer umsetzen
8
26
8
18
5
insert(30)
z
12
12
3
11
7
Trivial, dass die Laufzeit O(1) beträgt.
Faulheit rächt sich jedoch bei extractMax
Fibonacci Heaps: insert
Fibonacci Heaps: extractMax
Max
17
8
8
18
z
30
26
5
z
12
3
z
12
11
7
z
Extrahiere Maximum (Max-Pointer)
Mache alle Kinder zu nicht angeregter Wurzel
Durchlaufe alle Wurzeln, um neuen Maximum
zu finden
Währenddessen den Haufen aufräumen,
sodass alle Wurzeln paarweise
unterschiedlichen Grad besitzen:
z
Fibonacci Heaps: extractMax
Feld B[0..n-1] mit B[i] = v <=> deg(v) = i
Fibonacci Heaps: extractMax
Max
17
8
8
extractMax()
26
18
17
5
3
12
12
11
8
18
8
7
B[0]
5
12
3
B[1]
12
11
B[2]
7
B[3]
2
Fibonacci Heaps: extractMax
17
8
18
5
8
12
12
3
B[0]
B[1]
11
B[2]
Fibonacci Heaps: extractMax
17
7
B[3]
18
5
8
12
12
3
B[0]
B[1]
8
B[1]
11
B[2]
7
B[3]
12
12
11
B[2]
7
B[3]
17
8
Fibonacci Heaps: extractMax
5
3
B[0]
8
8
18
8
17
17
8
8
Fibonacci Heaps: extractMax
17
18
5
8
8
3
B[0]
B[1]
12
11
B[2]
17
17
8
8
18
12
7
B[3]
18
8
Fibonacci Heaps: extractMax
18
8
5
17
12
Fibonacci Heaps: extractMax
3
11
8
7
8
B[0]
B[1]
5
18
12
17
12
12
3
11
7
8
B[2]
B[3]
18
8 17
8
B[0]
B[1]
B[2]
5
3
B[3]
18
8 17
8
3
Fibonacci Heaps: extractMax
5
18
8
17
12
Fibonacci Heaps: extractMax
12
3
11
7
8
8
B[0]
17
12
12
3
11
7
8
B[1]
B[2]
B[3]
B[0]
B[1]
18
5
12
5
18
8 17
3
B[2]
18
5
12
8 17
3
8
B[3]
8
12
11 7
Fibonacci Heaps: extractMax
Fibonacci Heaps: extractMax
Max
5
12
18
8
3
B[0]
B[1]
12
5
17
12
8
11
B[2]
5
3
3
18
8
7
B[3]
z
z
8 17 12
8 11 7
aufräumen:
(1) für alle Wurzeln v:
(2) d = deg(v);
(3) wenn B[d] leer, dann B[d] = v;
(4) sonst:
(5)
mache kleinere Wurzel zum Kind der größeren;
(6)
v = größere Wurzel; // deg(v) ist jetzt d + 1
(7)
B[d] = leer;
(8)
goto (2);
z
17
12
8
11
7
Laufzeit: O(d + m)
z
18
Fibonacci Heaps: extractMax
z
12
d = deg(gelöschter Wurzel)
m = Anzahl der Wurzeln vor dem Löschen
genaue Analyse später
Fibonacci Heaps: increaseKey
z
increaseKey(v, newKey):
(1) erhöhe den Wert von v auf newKey;
(2) Heapeigenschaft verletzt? Nein fertig;
(3) sonst:
(4) u = Vater von v;
(5) mache v zu nicht angeregter Wurzel;
(6) ist u angeregt?
(7)
Nein rege ihn an;
(8)
Ja v = u; goto (4);
4
Fibonacci Heaps: increaseKey
Fibonacci Heaps: increaseKey
Max
17
8
8
Max
26
18
17
5
12
12
3 16
increaseKey(3, 16)
8
16
8
11
26
18
5
12
7
Fibonacci Heaps: increaseKey
11
8
16
8
Max
26
18
17
5
12
12
8
7 21
11
increaseKey(7, 21)
Fibonacci Heaps: increaseKey
Max
17
8
8
16
21
7
Fibonacci Heaps: increaseKey
Max
17
12
12
26
11
18
5
12
8
16
21
26
18
5
12
12
11
Analyse: Gradbeschränkung
Wir wollen zeigen, dass die Knotengrade im
Fibonacci Heap durch O(log n) beschränkt
sind.
z
Lemma: Sei x ein Knoten vom Grad d und
seien y1,…,yd die Kinder gemäß der
Reihenfolge beim Verlinken. Dann ist der
Grad von yi mindestens i – 2 für i = 1,…,d.
5
Analyse: Gradbeschränkung
z
Beweis: Wenn yi zu x gelinkt wurde, hatte x
schon y1,…, yi-1 Kinder.
deg(x) = i - 1
deg(yi) = i - 1, da wir nur Knoten gleichen Grades
verlinken.
Seitdem hat yi höchstens nur 1 Kind verloren (denn
ansonsten wäre er von x abgeschnitten)
Analyse: Gradbeschränkung
z
Sei φ eine Zahl mit 1 < φ ≤ 2 und 1 + φ ≥ φ3,
z.B. φ = 21/3 (ca. 1,26).
z
Lemma: Sei x ein Knoten vom Grad d. Dann
gilt: size(x) ≥ φd
⇒
⇒
z
size(x) = Anzahl der Knoten, die im von x
aufgespannten Unterbaum enthalten sind.
Y deg(yi) = i - 1 oder i - 2
Analyse: Gradbeschränkung
z
z
z
z
Beweis: Vollständige Induktion
Induktionsanfang: Wahr für d = 0
Induktionsannahme: Wahr für alle d < k
Induktionsbehauptung: d = k: size(x) ≥ φk
Analyse: Gradbeschränkung
z
Korollar: Der Grad d jedes Knotens x ist
beschränkt durch: O(log n).
z
Beweis:
n ≥ size(x) ≥ φd
size(x) = 1 + 3i≤k size(yi) ≥
Laut Induktionsannahme
≥ size(yk-1) + size(yk) ≥
≥ φk-3 + φk-2 = φk-3 (1 + φ) ≥
≥ φk-3 φ3 = φk.
Analyse: Laufzeit
z
n mal insert, danach extractMax → Θ(n)
z
z
z
z
z
Worst case. Schlechter als binärer Heap!
Aber selten so schlecht.
Intuition: insert baut Spannung/Potenzial auf, das
extractMax verlangsamt, sich aber dabei abbaut.
Nachfolgende extractMax haben es dafür leichter…
Potenzial baut sich nur langsam auf (über n EinfügeOperationen) → durchschnittliche Kosten über alle
Operationen ausschlaggebend.
Wir brauchen die amortisierte Analyse.
Y logφn ≥ d.
Amortisierte Analyse
Prinzip: Künstliche Verteuerung billiger Operationen,
damit teure Operationen die amortisierten Kosten
senken
z
z
Potentialmethode mittels Funktion Φ
Φ(D) besagt, wie schlecht die aktuelle Konfiguration
der Datenstruktur D ist
z
z
Hier: Φ bildet jeden Heap auf eine reelle Zahl ab
Operation: amortisierte Kosten = tatsächliche Kosten + ∆Φ
6
Amortisierte Analyse
z
Sei o1,...,on eine Folge von n Operationen
z
z
z
z
ai amortisierte Kosten für Operation oi
ti tatsächliche Kosten für Operation oi
Φi Potenzial direkt nach Operation oi
Φ0 Potenzial vor o1
Amortisierte Analyse
Dann ist die Summe der amortisierten Kosten
3ai = 3(ti + Φi - Φi-1) = 3ti + Φn - Φ0
z
z
Wir wählen eine Potenzialfunktion, die
z
z
z
z
Amortisierte Analyse
z
Konkrete Wahl von Φ?
z
Was kann später große Kosten verursachen?
z
z
Sicher Anzahl der Wurzeln W!
Provisorisch: Φ = αW
nichtnegativ und
am Anfang gleich Null ist
Dann ist Φn - Φ0 ≥ 0 und damit 3ai ≥ 3ti
und ai = ti + ∆Φ
A. Analyse: extractMax
fängt mit W1 Wurzeln an, hört mit W2 auf, entfernter
Knoten hatte Grad d
z tatsächliche Kosten ti = c(d + W1), c … Konstante
z ∆Φ = α(W2 – W1), amortisierte Kosten:
ai = c(d + W1) + α(W2 – W1) = (c – α)W1 + cd + αW2
z
z
z
Wir wählen α = c Y ai = cd + cW2
aber d = O(log n) und W2 = O(log n), denn alle
Wurzeln haben unterschiedlichen Grad
Y ai = O(log n)
A. Analyse: increaseKey
z
z
z
z
z
schafft k neue Wurzeln
tatsächliche Kosten ti = c´(k + 1), c´ … Konstante
Problem: teuer und erhöht Potenzial...
Zweite Quelle für Φ: aufgeregte Knoten A werden
leicht zu Wurzeln und verursachen dabei ebenfalls
Arbeit, also Φ = αW + βA
∆Φ ≤ αk + β(2 – k), denn alle neuen Wurzeln waren
aufgeregt (bis auf vielleicht eine), höchstens ein
Knoten regt sich neu auf.
A. Analyse: increaseKey
z
amortisierte Kosten
ai = c´(k + 1) + αk + β(2 – k)
= (c´ + α – β)k + c´+ 2β
z
ai = 3c´ + 2α = O(1)
z
Wähle β = c´+ α, es folgt
7
Analyse
z
Müssen wir extractMax neu abschätzen?
z
z
Nein, denn dort werden keine Knoten an- oder
abgeregt und A bleibt unberührt.
insert:
z
z
Erhöht die Anzahl der Wurzeln um 1
ai = ti+ α = O(1+ α) = O(1)
Resultat
z
Eine Folge von n insert- bzw.
increaseKey- und m ≤ n extractMaxOperationen auf einem anfänglich leeren
Fibonacci-Heap können in Zeit
O(n + m log n) ausgeführt werden.
Warum „Fibonacci“-Heap?
Verschärfte Version eines Lemmas, das wir
bewiesen haben:
z
Jeder Knoten vom Grad k hat mindestens
Fk+2 Nachkommen.
(k+2)-te Fibonacci-Zahl
8
Herunterladen