Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Amortisierte Analyse und Fibonacci Heaps. 2 Amortisierte Analyse - Modell Worst-Case-Laufzeiten für Einzeloperationen für die Abschätzung der Gesamtlaufzeit.

Ähnliche Präsentationen


Präsentation zum Thema: "Amortisierte Analyse und Fibonacci Heaps. 2 Amortisierte Analyse - Modell Worst-Case-Laufzeiten für Einzeloperationen für die Abschätzung der Gesamtlaufzeit."—  Präsentation transkript:

1 Amortisierte Analyse und Fibonacci Heaps

2 2 Amortisierte Analyse - Modell Worst-Case-Laufzeiten für Einzeloperationen für die Abschätzung der Gesamtlaufzeit häufig ungeeignet Idee: Statt Einzeloperationen, betrachte Sequenz von Operationen Op 1 -Op n Die Datenstruktur durchläuft dabei die Zustände S 0 …S n Die Laufzeiten für die Operationen sind T 1 …T n Die Gesamtzeit beträgt somit T = i T i Die Abschätzung bezieht sich auf die Sequenz, gibt aber durchschnittliche Kosten für die Einzeloperationen an!

3 3 Amortisierte Analyse Begriff der Amortisierung stammt aus der BWL: Eine teure Investition zahlt sich über längere Sicht hin aus und wird über die gesamte Zeit der Wirksamkeit der Investition amortisiert. Auf Algorithmen zum ersten Mal Anfang der 80er Jahre angewandt [Brown, Huddleston, Mehlhorn, Sleator, Tarjan u.a.] Abgrenzung zur Average-Case-Analyse –Keine Wahrscheinlichkeiten notwendig! –Ergebnis: durchschnittliche Laufzeit jeder Operation im schlimmsten Fall! Leistungsgarantie!

4 4 Beispiel: Binärzähler Sequenz: Zählen für k = 0…N Operation: Inkrementieren Kosten: Ändern einer Ziffer (0 ! 1 oder 1 ! 0) Betrachte –Kosten pro Operation T k+1 (# invertierte Bits für k ! k + 1) –Gesamtkosten T kbin(k)

5 5 Beispiel: Binärzähler Beobachtung 1 · T k · 1 + d log k e Worst-Case-Abschätzung T k = 1 + d log k e T = N ¢ (1+ d log N e ) kbin(k)TkTk

6 6 Beispiel: Binärzähler Beobachtung 1 · T k · 1 + d log k e Worst-Case-Abschätzung T k = 1 + d log k e T = N ¢ (1+ d log N e ) Weitere Beobachtung T k · 2 k kbin(k)TkTk T k

7 7 Beispiel: Binärzähler

8 8

9 9 Binärzähler: Analyse kbin(k)TkTk T k

10 10 Binärzähler: Analyse B[0] wird jeden Schritt invertiert kbin(k)TkTk T k

11 11 Binärzähler: Analyse B[0] wird jeden Schritt invertiert B[1] wird jeden zweiten Schritt invertiert B[k] wird alle 2 k Schritte invertiert kbin(k)TkTk T k

12 12 Binärzähler: Analyse Addition über die Zeilen der Tabelle lieferte uns Addition über die Spalten hingegen Laufzeit für das Zählen von k = 0…N: O (N) Amortisierte Laufzeit für Inkrement: O (N)/N = O (1)

13 13 Aggregatmethode Berechne die Gesamtkosten für eine Sequenz von Operationen Division der Gesamtkosten durch die Zahl der Operationen liefert amortisierte Kosten pro Operation Dieses Vorgehen heißt Aggregatmethode und ist die einfachste Technik der amortisierten Analyse. Die zweite wichtige Technik ist die Bankkonto-Methode (siehe 5. Übungsblatt!)

14 14 Potenzialmethode Idee: Operationen können potenzielle Energie erzeugen/verbrauchen Die Funktion ordnet jedem Zustand S i unserer Datenstruktur ein Potenzial (S i ) zu Die amortisierten Kosten a i der Operation Op i hängen von den tatsächlichen Kosten c i und dem Potenzial ab Die Gesamtkosten der N Operationen sind damit

15 15 Potenzialfunktionen Billige Operationen erhöhen das Potenzial über ihre eigenen Kosten hinaus: a i > c i Teure Operationen verringern das Potenzial, bezahlen also einen Teil der Operation mit dem was die vorhergehenden billigen Operationen an Potenzieller Energie angesammelt haben: a i < c i Für (S N ) ¸ (S 0 ) sind die amortisierten Kosten der N Operationen eine obere Schranke für die tatsächlichen Kosten

16 16 Potenzialverlauf i N

17 17 Binärzähler mit der Potenzialmethode Definiere das Potenzial als Anzahl der gesetzten Bits im derzeitigen Zählerstand: (S i ) = i = #1 2 bin(i) Der Zählerstand sei i und der Übergang zu i+1 soll t i Bits zurücksetzen (1 ! 0). Ferner wird maximal ein weiteres Bit gesetzt ) c i = t i + 1 Für die Potenzialänderung gilt dann: i - i-1 · i-1 - t i i-1 = 1- t i Damit gilt für die amortisierten Kosten: a i = c i i-1 · (t i +1) + (1– t i ) = 2 ) O (1)

18 18 Amortisierte Analyse von Heaps OperationBinärer HeapBinomial-Heap insert O (log N) find_min O (1) delete_min O (log N) decrease_key O (log N) create O (N) merge O (N) O (log N)

19 19 Amortisierte Analyse von Heaps OperationBinärer HeapBinomial-HeapFibonacci-Heap insert O (log N) ? find_min O (1) ? delete_min O (log N) ? decrease_key O (log N) ? create O (N) ? merge O (N) O (log N)?

20 20 Fibonacci-Heaps Def.: Ein Fibonacci-Heap ist eine Datenstruktur, die einen Wald von Bäumen mit Heapeigenschaft besitzt. Jeder der Knoten (außer den Wurzeln) trägt ein zusätzliches Markierungsbit mark. Das Element min zeigt auf die kleinste Wurzel des Walds. Die Wurzeln sind doppelt zyklisch verkettet, ebenso die Kinder eines jeden Knotens.

21 21 Fibonacci-Heaps Def.: Ein Fibonacci-Heap ist eine Datenstruktur, die einen Wald von Bäumen mit Heapeigenschaft besitzt. Jeder der Knoten (außer den Wurzeln) trägt ein zusätzliches Markierungsbit mark. Das Element min zeigt auf die kleinste Wurzel des Walds. Die Wurzeln sind doppelt zyklisch verkettet, ebenso die Kinder eines jeden Knotens. =

22 22 Fibonacci-Heaps Def.: Ein Fibonacci-Heap ist eine Datenstruktur, die einen Wald von Bäumen mit Heapeigenschaft besitzt. Jeder der Knoten (außer den Wurzeln) trägt ein zusätzliches Markierungsbit mark. Das Element min zeigt auf die kleinste Wurzel des Walds. Die Wurzeln sind doppelt zyklisch verkettet, ebenso die Kinder eines jeden Knotens.

23 23 Fibonacci-Heaps Def.: Ein Fibonacci-Heap ist eine Datenstruktur, die einen Wald von Bäumen mit Heapeigenschaft besitzt. Jeder der Knoten (außer den Wurzeln) trägt ein zusätzliches Markierungsbit mark. Das Element min zeigt auf die kleinste Wurzel des Walds. Die Wurzeln sind doppelt zyklisch verkettet, ebenso die Kinder eines jeden Knotens. min

24 24 Fibonacci-Heaps Def.: Ein Fibonacci-Heap ist eine Datenstruktur, die einen Wald von Bäumen mit Heapeigenschaft besitzt. Jeder der Knoten (außer den Wurzeln) trägt ein zusätzliches Markierungsbit mark. Das Element min zeigt auf die kleinste Wurzel des Walds. Die Wurzeln sind doppelt zyklisch verkettet, ebenso die Kinder eines jeden Knotens min

25 25 Fibonacci-Heaps Def.: Ein Fibonacci-Heap ist eine Datenstruktur, die einen Wald von Bäumen mit Heapeigenschaft besitzt. Jeder der Knoten (außer den Wurzeln) trägt ein zusätzliches Markierungsbit mark. Das Element min zeigt auf die kleinste Wurzel des Walds. Die Wurzeln sind doppelt zyklisch verkettet, ebenso die Kinder eines jeden Knotens min

26 26 Fibonacci-Heaps Def.: Ein Fibonacci-Heap ist eine Datenstruktur, die einen Wald von Bäumen mit Heapeigenschaft besitzt. Jeder der Knoten (außer den Wurzeln) trägt ein zusätzliches Markierungsbit mark. Das Element min zeigt auf die kleinste Wurzel des Walds. Die Wurzeln sind doppelt zyklisch verkettet, ebenso die Kinder eines jeden Knotens min mark = true mark = false

27 27 FibonacciHeap – Interface template class FibonacciHeap { public: typedef std::pair Item; typedef FibonacciNode* NodePtr; const Item& find_min() const; void delete_min(); void insert(const Item& item); void create(const std::vector & array); void merge(FibonacciHeap& heap); void decrease_key(NodePtr item, const Key& key);

28 28 FibonacciHeap – Interface protected: // Hilfsmethoden void consolidate(); void cut(NodePtr node); void cascading_cut(NodePtr node); void link(NodePtr root, NodePtr child); void insert_into_rootlist(NodePtr node); void erase_from_rootlist(NodePtr node); unsigned int max_deg() const; // max. Grad der Wurzeln // Attribute int number_of_nodes; // Gesamtzahl Knoten NodePtr min; // Minmale Wurzel // min ist auch der Anfang der Wurzelliste! };

29 29 FibonacciNode – Interface template class FibonacciNode { public: typedef FibonacciNode* NodePtr; const Key& key() const { return key; } Key& key() { return key; } // Accessoren für Attribute […] unsigned int degree() const; // Grad = Anzahl Kinder void remove_child(NodePtr child); // Entferne Kind aus Liste protected: Key key; // Der Schlüssel Inf inf; // Die Information NodePtr left; // Linker Geschwisterknoten NodePtr right; // Rechter Geschwisterknoten NodePtr parent; // Elterknoten NodePtr first_child; // Erster Kinderknoten bool mark; // Markierung };

30 30 find_min, merge im Fibonacci-Heap merge –Vereinige die Wurzellisten –min (H) = min( min (H 1 ), min (H 2 )) ) O (1) find_min: O (1) min min

31 31 insert im Fibonacci-Heaps min 1 Knoten wird neben dem Minimum in der Wurzelliste eingefügt, der Zeiger auf das Minimum gegebenenfalls angepasst ) O (1)

32 32 insert im Fibonacci-Heaps min 1 Knoten wird neben dem Minimum in der Wurzelliste eingefügt, der Zeiger auf das Minimum gegebenenfalls angepasst ) O (1)

33 min delete_min im Fibonacci-Heap void delete_min() { NodePtr node = min(); if (node == 0) throw Empty heap!; Für jedes Kind child von node: child.parent = 0; insert_into_rootlist(child); erase_from_rootlist(node); if (node->right == node) { min() = 0; } else { min() = node->right; consolidate(); } delete node; number_of_nodes--; }

34 34 delete_min im Fibonacci-Heap void delete_min() { NodePtr node = min(); if (node == 0) throw Empty heap!; Für jedes Kind child von node: child.parent = 0; insert_into_rootlist(child); erase_from_rootlist(node); if (node->right == node) { min() = 0; } else { min() = node->right; consolidate(); } delete node; number_of_nodes--; } 2314 min

35 35 delete_min im Fibonacci-Heap void delete_min() { NodePtr node = min(); if (node == 0) throw Empty heap!; Für jedes Kind child von node: child.parent = 0; insert_into_rootlist(child); erase_from_rootlist(node); if (node->right == node) { min() = 0; } else { min() = node->right; consolidate(); } delete node; number_of_nodes--; } 23 min

36 36 delete_min im Fibonacci-Heap void delete_min() { NodePtr node = min(); if (node == 0) throw Empty heap!; Für jedes Kind child von node: child.parent = 0; insert_into_rootlist(child); erase_from_rootlist(node); if (node->right == node) { min() = 0; } else { min() = node->right; consolidate(); } delete node; number_of_nodes--; } 23 min

37 37 consolidate im Fibonacci-Heap insert und delete_min erhöhen die Anzahl der Bäume Gelegentlich muss die Zahl der Bäume reduziert werden ) consolidate Idee: Verschmelze Bäume gleichen Grads in der Wurzel bis nur noch Bäume mit unterschiedlichem Grad übrig bleiben. Erhalte dabei die Heapeigenschaft.

38 38 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; // Löscht Wurzelliste! 23 min A d0xy

39 39 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

40 40 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

41 41 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

42 42 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

43 43 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

44 44 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

45 45 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

46 46 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

47 47 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

48 48 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

49 49 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

50 50 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

51 51 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

52 52 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

53 53 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy void link(NodePtr root, NodePtr child) { remove_from_root_list(child); root.insert_child(child); child->mark() = false; }

54 54 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy void link(NodePtr root, NodePtr child) { remove_from_rootlist(child); root.insert_child(child); child->mark() = false; }

55 55 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy void link(NodePtr root, NodePtr child) { remove_from_rootlist(child); root.insert_child(child); child->mark() = false; }

56 56 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

57 57 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

58 58 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d2xy

59 59 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d2xy

60 60 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d2xy

61 61 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

62 62 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

63 63 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

64 64 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

65 65 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

66 66 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d0xy

67 67 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

68 68 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

69 69 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

70 70 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

71 71 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

72 72 consolidate im Fibonacci-Heap void consolidate() { vector A(max_deg() + 1); NodePtr v, x, y; Für alle Knoten v aus root_list: { x = v; int d = x->degree(); while (A[d] != 0) { y = A[d]; if (x->key() > y->key()) std::swap(x, y) link(x, y); A[d] = 0; d++; } A[d] = x; } min() = 0; 23 min A d1xy

73 73 consolidate im Fibonacci-Heap void consolidate() { […] for (i = 0; i < A.size(); i++) { if (A[i] != 0) { insert_into_rootlist(A[i]); if (min() == 0 || A[i]->key() key()) { min() = A[i]; } 23 min A d1xy

74 74 Potenzialfunktion zur amortisierten Analyse Der Fibonacci-Heap H enthalte N Knoten M sei die Anzahl markierter Knoten ( mark = true) T sei die Anzahl der Bäume in der Wurzelliste Es existiere ein maximaler Grad D aller Knoten Wir wählen die Potenzialfunktion als ( H) = T(H) + 2 M(H) hat folgende Eigenschaften –Für einen leeren Heap ist = 0 –Für zwei Heaps H 1 und H 2 gilt (H 1 [ H 2 ) = (H 1 ) + (H 2 )

75 75 Amortisierte Analyse von insert insert : neuer Knoten wird neben dem Minimum in der Wurzelliste eingefügt, der Zeiger auf das Minimum gegebenenfalls angepasst Analyse: –# Bäume erhöht sich: T i+1 = T i + 1 –# Markierungen konstant: M i+1 = M i ) = i+1 - i = (T i M i ) – (T i – 2 M i ) = 1 Worst-Case-Laufzeit und amortisierte Laufzeit O (1)

76 76 Analyse von delete_min void delete_min() { NodePtr node = min(); if (node == 0) throw Empty heap!; Für jedes Kind child von node: // max. O (D) Kinder! child.parent = 0; insert_into_rootlist(child); erase_from_rootlist(node); // T i+i = T i + D - 1 if (node->right == node) { min() = 0; } else { min() = node->right; consolidate(); } delete node; number_of_nodes--; }

77 77 Analyse von delete_min void delete_min() { NodePtr node = min(); if (node == 0) throw Empty heap!; Für jedes Kind child von node: // max. O (D) Kinder! child.parent = 0; insert_into_rootlist(child); erase_from_rootlist(node); // T i+i = T i + D - 1 if (node->right == node) { min() = 0; } else { min() = node->right; consolidate(); // Analyse von consolidate? } delete node; number_of_nodes--; }

78 78 Analyse von consolidate vector A(max_deg() + 1); // O (D i ) Für alle Knoten v aus root_list: // O (T i ) […] while (A[d] != 0) { […] d++; } A[d] = x; min() = 0; // T i+1 = 0? for (i = 0; i < A.size(); i++) // O (D i ) { if (A[i] != 0) { insert_into_rootlist(A[i]); // T i+1 · D i + 1 […] }

79 79 Analyse von delete_min void delete_min() { NodePtr node = min(); if (node == 0) throw Empty heap!; Für jedes Kind child von node: // O (D i ) child.parent = 0; insert_into_rootlist(child); erase_from_rootlist(node); // T i+i = T i + D i - 1 if (node->right == node) { min() = 0; } else { min() = node->right; consolidate(); // O (T i + D i ) } delete node; number_of_nodes--; }

80 80 Analyse von delete_min Die tatsächlichen Kosten c i für delete_min sind c i = O (D i + T i ) Für das Potenzial vor der Ausführung von delete_min gilt: i = T i + 2 M i Nach der Ausführung bleiben maximal T i+1 = D i +1 Wurzeln übrig. Ferner werden keine Knoten neu markiert, d.h. M i+1 = M i. Daher gilt für i+1: i+1 = T i M i+1 = D i M i Die amortisierten Kosten a i betragen somit a i = c i + i+1 - i = O (D i + T i ) + D i M i – T i – 2 M i = O (D i + T i ) + D i + 1 – T i = O (D i ) + O (T i ) – T i = O (D i ) Der letzte Schritt ist möglich, da sich stets so skalieren lässt, dass die in O (T i ) versteckten Konstanten kompensiert werden und O (T i ) – T i verschwindet.

81 81 Bestimmung des maximalen Grades D ||x|| sei die Anzahl der Knoten im Unterbaum von Knoten x inklusive x. grad(x) sei der Grad (Anzahl der Kinder) von Knoten x. Lemma 1: Sei x irgendein Knoten in einem Fibonacci-Heap mit Grad k. Seien y 1, y 2, …, y k die Kinder von x in der Reihenfolge in der sie hinzugefügt wurden. Dann gilt: grad(y 1 ) ¸ 0 und grad(y i ) ¸ i – 2 8 i = 2, 3, …, k Beweis: grad(y 1 ) ¸ 0 ist trivial. Als y i ein Kind von x wurde, waren y 1, …, y i-1 bereits Kinder, d.h. grad(x) war (i – 1). consolidate wird y i nur zu einem Kind von x machen, wenn grad(x) = grad(y i ). Da y i seit dem einfügen höchstens ein Kind verloren, nicht aber dazugewonnen, haben kann, gilt also: grad(y i ) ¸ i – 2.

82 82 Fibonacci Ein Problem im Liber Abaci des Leonardo von Pisa (genannt Fibonacci) lautet: Jemand setzt ein Paar Kaninchen in einen Garten, der auf allen Seiten von einer Mauer umgeben ist, um herauszufinden, wie viele Kaninchen innerhalb eines Jahre geboren werden. Wenn angenommen wird, dass jeden Monat jedes Paar ein weiteres Paar erzeugt, und dass Kaninchen zwei Monate nach ihrer Geburt geschlechtsreif sind, wie viele Paare Kaninchen werden dann jedes Jahr geboren?

83 83 Die Fibonacci-Zahlen Lemma 2: Für alle k 2 N gilt Beweis: Induktion über k. k = 0: 1 + F_0 = = F_2 Mit der Behauptung F k+1 = 1 + i=0 k-1 F i erhält man für F k+2

84 84 Bestimmung des maximalen Grades D Lemma 3: Sei x irgendein Knoten in einem Fibonacci-Heap und grad(x) = k. Dann gilt: Beweis: Sei s k der minimale Wert ||z|| eines Knotens z mit grad(z) = k. Offensichtlich gilt s 0 = 1, s 1 = 2, s 2 = 3. Ebenso ist s k nicht größer als ||x|| und die s k wachsen monoton mit k. Ferner seien y 1, y 2,…y k die Kinder von x in der Reihenfolge in der sie eingefügt wurden. Um eine untere Schranke für ||x|| zu berechnen, zählen wir eine Eins für x selbst und für y 1 und wenden dann Lemma 1 an: Lemma 1: grad(y 1 ) ¸ 0 und grad(y i ) ¸ i – 2 8 i = 2, 3, …, k

85 85 Bestimmung des maximalen Grades D Mit vollständiger Induktion über k lässt sich zeigen, dass s k ¸ F k+2 für alle k: k = 0: s 0 = 1 ¸ 0 = F 0 k = 1: s 1 = 2 ¸ 1 = F 1 Mit der Induktionsbehauptung gilt: Ferner glauben wir (ohne Beweis), dass F k+2 ¸ n. Korollar: Der maximale Grad D(N) eines jeden Knotens in einem Fibonacci-Heap mit N Knoten ist O (log N). Beweis: Sie x ein Knoten des Heaps und grad(x) = k. Nach Lemma 3 gilt: N ¸ ||x|| ¸ k Durch Logarithmieren erhält man: log N ¸ k

86 86 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15

87 87 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15

88 88 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15

89 89 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15

90 90 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15

91 91 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; }

92 92 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; }

93 93 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; }

94 94 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; }

95 95 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; }

96 96 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15

97 97 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); }

98 98 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); }

99 99 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); }

100 100 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey15

101 101 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5

102 102 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5

103 103 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5

104 104 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5

105 105 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; }

106 106 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; }

107 107 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; }

108 108 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; } 5

109 109 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 void cut(NodePtr node) { if (node->parent() == 0) throw Cannot cut root!; // Entferne Knoten aus Elterknoten node->parent()->remove_child(node); node->parent() = 0; // Füge in Wurzelliste ein insert_into_rootlist(node); // Entferne mögliche Markierung node->mark() = false; } 5

110 110 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); }

111 111 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); }

112 112 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); }

113 113 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 26

114 114 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 26

115 115 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 26

116 116 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 26

117 117 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 26

118 118 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 26

119 119 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 26 24

120 120 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 2624

121 121 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 2624

122 122 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey5 5 void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; } else { cut(node); cascading_cut(node->parent()); } 2624

123 123 decrease_key im Fibonacci-Heap void decrease_key(NodePtr node, const Key& key) { if (node.key() < key) throw No decrease!; // Konsistenzcheck node.key() = key; // Neuen Schlüssel zuweisen NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { // Heapeigenschaft verletzt! cut(node); cascading_cut(p); } if (key < min()) min() = node; // Minimum anpassen } min nodekey

124 124 Analyse von decrease_key void decrease_key(NodePtr node, const Key& key) { […] NodePtr p = node->parent(); if (node->parent() != 0 && node->parent->key() > key) { cut(node); // O (1) cascading_cut(p); // ??? } if (key < min()) min() = node; } void cut(NodePtr node) { […] node->parent()->remove_child(node); // O (1) […] insert_into_rootlist(node); // O (1), T erhöht node->mark() = false; // evtl. M erniedrigt }

125 125 Analyse von cascading_cut void cascading_cut(NodePtr node) { if (node->parent() == 0) return; if (node->mark() == false) { node->mark() = true; // M um eins erhöht! } else { cut(node); // O (1), T erhöht // evtl. M erniedrigt cascading_cut(node->parent()); // Rekursion! } Unter der Annahme von r rekursiven Aufrufen von cascading_cut ist die tatsächliche Arbeit in cascading_cut O (r). Jeder Aufruf von cascading_cut, mit Ausnahme des letzten, entfernt einen markierten Knoten und fügt ihn in die Wurzelliste ein. Dabei werden die Markierungen von (r – 1) Knoten entfernt und eventuell ein weiterer Knoten markiert.

126 126 Analyse von decrease_key Tatsächliche Arbeit in decrease_key O (1) + O (r) Potenzialänderung –r Bäume erzeugt: T i+1 = T i + r –max. (2 – r ) Markierungen erzeugt: M i+1 = M i – r + 2 ) = r + 2 (2 – r) = 4 + r Amortisierte Kosten: a i = c i + = O (r) + 4 – r = O (1) Die letzte Umformung folgt wieder aus der Skalierbarkeit des Potenzials

127 127 Amortisierte Analyse von Heaps OperationBinärer HeapBinomial-Heap Fibonacci-Heap (amortisiert) insert O (log N) O (1) find_min O (1) delete_min O (log N) Decrease_key O (log N) O (1) create O (N) merge O (N) O (log N) O (1)


Herunterladen ppt "Amortisierte Analyse und Fibonacci Heaps. 2 Amortisierte Analyse - Modell Worst-Case-Laufzeiten für Einzeloperationen für die Abschätzung der Gesamtlaufzeit."

Ähnliche Präsentationen


Google-Anzeigen