Informatik II Algorithmen und Datenstrukturen Vorläufige Version 1 c 2002 Peter Thiemann 1 Einführung 1.1 Inhalt • Wichtige Datentypen und ihre Implementierung (Datenstrukturen) • Operationen auf Datenstrukturen (Algorithmen) • Komplexitätsanalyse – Laufzeitanalyse der Operationen – Speicherverbrauchsanalyse • Techniken des Algorithmenentwurfs • Informell: Korrektheit der Algorithmen Vorläufige Version 2 c 2002 Peter Thiemann 1.2 Ziele • Reproduktion • Anwendung • Implementierung • Auswahlkriterien • Komplexitätsanalyse einfacher Algorithmen • Entwurfsideen für Algorithmen Vorläufige Version 3 c 2002 Peter Thiemann 1.3 Hilfsmittel • elementare Mathematik (Folgen, Reihen, Grenzwerte, Abschätzungen, Kombinatorik) • algorithmische Notation z.B. Programmiersprache Vorläufige Version 4 c 2002 Peter Thiemann 1.4 Literatur • T. Ottmann und P. Widmayer, Algorithmen und Datenstrukturen, 4. Auflage, Spektrum Verlag, 2001. Vorläufige Version 5 c 2002 Peter Thiemann 2 Grundlagen der Komplexitätsanalyse Referenzmaschine für Komplexitätsanalyse: Turingmaschine Definition 1 Sei M Turingmaschine für einen Algorithmus A(x) 1. Laufzeit von A bei Eingabe von x T (x) = ] Schritte, die M zur Berechnung von A(x)benötigt 2. Speicherplatzbedarf von A bei Eingabe von x S(x) = ] Bandplätze, die M zur Berechnung von A(x)benötigt Weitere Möglichkeiten für Referenzmaschinen 1. RAM (random access machine) 2. RM (register machine) Vorläufige Version 6 c 2002 Peter Thiemann Beispiel: tm-find0 Turingmaschine über Alphabet {0, 1}, die feststellt, ob die Eingabe 0 enthält. 1 1 0 1 1 0 q0 q0 1 B 1 N,0,qf R,B,q0 N,B,qf Startzustand q0 ; Endzustand qf ; akzeptiert, falls Kopf auf nicht-leerem Platz Vorläufige Version x 0 1 110 110111 T(x) 1 2 3 3 S(x) 1 1 3 6 7 c 2002 Peter Thiemann Probleme mit der Definition 1. Komplexität hängt von konkreter Eingabe ab 2. Exakte Schrittzahl selten von Interesse 3. Algorithmen werden nicht in Form von Turingmaschinen aufgeschrieben Vorläufige Version 8 c 2002 Peter Thiemann 2.1 Abstraktion von der Eingabe • Anstatt konkreter Eingabe x betrachte alle Eingaben der Größe n = |x| • Bestimme Anzahl der Schritte/Plätze in Abhängigkeit von n ⇒ neues Problem: Eingaben gleicher Größe können unterschiedlich viele Schritte/Plätze verbrauchen • im Beispiel tm-find0 – Eingabe 00000000 braucht einen Schritt – Eingabe 11101111 braucht vier Schritte – Eingabe 11111111 braucht neun Schritte Vorläufige Version 9 c 2002 Peter Thiemann Arten von Komplexität Lösung: extrahiere einen Wert aus allen Werten T (x) mit |x| = n • Tmin (n) = min{T (x) | |x| = n} best-case Komplexität • Tmax (n) = max{T (x) | |x| = n} worst-case Komplexität P • T (n) = |x|=n T (x) · qn (x) qn (x) ist Wahrscheinlichkeit, dass x als Eingabe der Größe n auftritt average-case Komplexität Vorläufige Version 10 c 2002 Peter Thiemann Bewertung • best-case Komplexität leicht zu bestimmen, meist unwichtig • worst-case Komplexität oft zu pessimistisch • average-case Komplexität – praktisch relevant – schwierig zu bestimmen – Wahrscheinlichkeitsverteilung meist unbekannt in Beweisen wird oft Gleichverteilung angenommen d.h. qn (x) = m−1 wobei m = |{x | |x| = n}| Vorläufige Version 11 c 2002 Peter Thiemann Beispiel: Laufzeitanalyse von tm-find0 • best-case Tmin (n) = 1 falls x = 0 . . . or x = ε • worst-case Tmax (n) = n + 1 falls x = 1 . . . 1 • average-case Annahme: Gleichverteilung, d.h. qn (x) = 2−n T (n) Vorläufige Version = 1 · 0.5 + 2 · (0.5)2 + . . . + n · (0.5)n + (n + 1) · (0.5)n Pn = ( k=1 k · 2−k ) + (n + 1) · 2−n 12 (1) c 2002 Peter Thiemann Nebenrechnung Pn k=1 k · 2−k = 1 · 2−1 = + 2 · 2−2 2−1 + 3 · 2−3 + . . . + n · 2−n + 2−2 + 2−3 +...+ 2−n + 2−2 + 2−3 +...+ 2−n + −3 +...+ .. . −n 2 + 2 (2) 2−n Jede Zeile von (2) ist (Endstück einer) geometrischen Folge n X q n+1 − 1 q = q−1 (3) (1/2)n+1 − 1 (1/2) = = −2(1/2)n+1 + 2 = 2 − 2−n 1/2 − 1 (4) k=0 k Einsetzen von q = 1/2 in (3) ergibt n X k=0 Vorläufige Version k 13 c 2002 Peter Thiemann In Zeile j ∈ {1, . . . , n} von (2) steht gerade 2−j + 2−(j+1) + . . . + 2−n = Pn = (4) 2 − 2−n − (2 − 2−(j−1) ) = −2−n + 2−(j−1) k k=0 (1/2) − Pj−1 k k=0 (1/2) Also ergibt die Summe aller Zeilen in (2): Pn −n + 2−(j−1) = j=1 −2 −n · 2−n + = −n · 2−n + (4) −n · 2−n + 2 − 2−(n−1) = (5) Pn −(j−1) j=1 2 Pn−1 −j j=0 2 (6) Einsetzen von (6) in (1) ergibt insgesamt T (n) = −n · 2−n + 2 − 2−(n−1) + (n + 1) · 2−n = 2 + 2−n − 2−(n−1) −n = 2+2 = Vorläufige Version −2·2 −n (7) 2 − 2−n 14 c 2002 Peter Thiemann 2.2 Komplexität eines Problems Unterschied: Komplexität eines Problems ↔ Komplexität eines Algorithmus • Komplexität eines Problems ist die minimale Laufzeit (Speicherplatzbedarf) eines Algorithmus, der das Problem löst Theorie: für manche Probleme gibt es untere Schranken, d.h. kein Algorithmus kann schneller laufen, als die untere Schranke angibt oft schwer zu bestimmen • Komplexität eines konkreten Algorithmus liefert obere Schranke für ein Problem • Falls die Komplexität eines Algorithmus der unteren Schranke eines Problems entspricht, so liegt eine genaue Schranke vor. Vorläufige Version 15 c 2002 Peter Thiemann 2.3 Wachstumsklassen von Funktionen • Genaue Zahl von Schritten selten interessant und/oder technisch aufwändig zu ermitteln • Variiert zwischen Implementierungen • Verhalten wichtiger für große Eingaben asymptotisches Verhalten • Unabhängigkeit von konstanten Faktoren Änderung bei Technologiewechsel ⇒ Wachstumsverhalten von Funktionen ist interessanter Vorläufige Version 16 c 2002 Peter Thiemann Definition: Landausche O-Notation Seien f, g : N → R+ Funktionen • f ∈ O(g) “f wächst nicht schneller als g”, falls (∃c ∈ R+ ) (∃n0 ∈ N) (∀n ∈ N) n > n0 ⇒ f (n) ≤ c · g(n) • f ∈ Ω(g) “f wächst mindestens so schnell wie g”, falls g ∈ O(f ) • f ∈ Θ(g) “f genauso schnell wie g”, falls f ∈ O(g) und g ∈ O(f ) • f ∈ o(g) “f wächst langsamer als g”, falls f (n) =0 n→∞ g(n) lim • f ∈ ω(g) “f wächst schneller als g”, falls g ∈ o(f ) Vorläufige Version 17 c 2002 Peter Thiemann Schreibweise • Schreibe O(n log n) anstelle von – O(λn.n log n) oder – O(g) mit g(n) = n log n • Oft: f = O(g) anstatt f ∈ O(g) Vorsicht, da Gesetze von = nicht gelten! Vorläufige Version 18 c 2002 Peter Thiemann Beispiele √ n; f2 (n) = n; f3 (n) = nk für k ≥ 1; f4 (n) = 2n √ • f1 ∈ O(f2 ), denn für alle n > n0 = 1 gilt: n ≤ n (mit c = 1) Sei f1 (n) = • f2 ∈ O(f3 ), denn für alle n > n0 = 1 gilt: n ≤ nk (mit c = 1; für alle k ≥ 1) • f3 ∈ O(f4 ), denn es gilt sogar f3 ∈ o(f4 ): nk k · nk−1 k! lim n = lim = . . . = lim =0 n→∞ ln 2 · 2n n→∞ (ln 2)k · 2n n→∞ 2 nach l´Hospital (k-fach angewendet) Zur Erinnerung: Regel von l´Hospital f 0 (n) lim =c n→∞ g 0 (n) ⇒ f (n) =c n→∞ g(n) lim falls limn→∞ f (n) = limn→∞ g(n) ∈ {0, ±∞} Vorläufige Version 19 c 2002 Peter Thiemann Visualisierung des Größenwachstums 20 log(x) sqrt(x) x x*x x*x*x x*x*x*x exp(x) 15 10 5 0 Vorläufige Version 0 5 10 15 20 20 c 2002 Peter Thiemann Wachstumshierarchie Vorläufige Version O(1): konstante Funktionen O(log n): Logarithmische Funktionen O(log2 n): Quadratisch logarithmische Funktionen O(n): Lineare Funktionen O(n log n): — keine spezielle Bezeichnung — O(n2 ): quadratische Funktionen O(n3 ): kubische Funktionen O(nk ): polynomielle Funktionen (für festes k ≥ 1) genauer: f heißt polynomiell beschränkt, wenn es ein Polynom p mit f = O(p) gibt O(2n ): exponentielle Funktionen genauer: f wächst exponentiell, wenn es ein > 0 mit f = Θ(2n ) gibt 21 c 2002 Peter Thiemann Skalierbarkeit Maximale Eingabelänge bei gegebener Rechenzeit Annahme: Rechenschritt 0.001 Sekunden. Laufzeit T(n) Vorläufige Version 1 Sekunde 1 Minute 1 Stunde n 1000 60000 3600000 n log n 140 4895 204094 n2 31 244 1897 n3 10 39 153 2n 9 15 21 22 c 2002 Peter Thiemann Maximale Eingabelänge in Abhängigkeit von Technologie • Algorithmus mit Laufzeit T (n) • p max. Eingabelänge mit alter Technologie • pneu max. Eingabelänge mit neuer Technologie • neue Technologie: 10-mal so schnell • 10 · T (p) = T (pneu ) T (n) pneu n 10p (fast 10)p log 10p = log p + log 10 ≈ log p n2 3.16p 3.162 ≈ 10 n3 2.15p 2.153 ≈ 10 2n p + 3.3 23.3 ≈ 10 n log n Vorläufige Version Begründung 23 c 2002 Peter Thiemann Beispiel: Exponentieller Algorithmus SAT (Erfüllbarkeit einer Formel der Aussagenlogik) Frage: Gegeben eine logische Formel mit n Variablen. Gibt es eine Belegung der Variablen, so dass die Formel wahr (erfüllt) ist? Alternativ: Gegeben ein kombinatorischer Schaltkreis mit n Eingängen. Gibt es eine Belegung der Eingänge, so dass der Ausgang 1 ist? Naive Lösung: Durchprobieren aller 2n möglichen Belegungen. ⇒ exponentielle Laufzeit Anmerkung: Es ist nicht bekannt, ob dieser Algorithmus der bestmögliche ist. Vorläufige Version 24 c 2002 Peter Thiemann Weitere Eigenschaften • Falls p1 und p2 Polynome vom Grad d1 bzw. d2 mit positivem Leitkoeffizienten sind, so gilt p1 ∈ Θ(p2 ) ⇔ d1 = d2 p1 ∈ o(p2 ) ⇔ d 1 < d2 p1 ∈ ω(p2 ) ⇔ d 1 > d2 • Für alle k > 0 und ε > 0 gilt logk n ∈ o(nε ) dabei ist logk n = (log n)k • 2n/2 ∈ o(2n ) Vorläufige Version 25 c 2002 Peter Thiemann Rechenregeln für O • f ∈ O(f ) • O(f ) = O(O(f )) • O(k · f ) = O(f ) für Konstante k ≥ 0 • O(k + f ) = O(f ) für Konstante k ≥ 0 • O(f ) · O(g) = O(f · g) Multiplikationsregel • O(f ) + O(g) = O(max(f, g)) Vorläufige Version Additionsregel 26 c 2002 Peter Thiemann Beweis für Additions- und Multiplikationsregel Sei F ∈ O(f ) und G ∈ O(g), d.h. es gibt cF , cG ∈ R+ sowie nF , nG ∈ N, sodass (∀n > nF ) F (n) ≤ cF f (n) und (∀n > nG ) G(n) ≤ cG g(n) ist. Sei nun n0 = max(nF , nG ). Offenbar gilt für c1 = cF · cG , dass (∀n > n0 ) F (n) · G(n) ≤ cF f (n) · cG g(n) = c(f · g)(n). Es gilt also die Multiplikationsregel: F · G ∈ O(f · g). Weiter gilt für c2 = cF + cG , dass (∀n > n0 ) F (n) + G(n) ≤ cF f (n) + cG g(n) ≤ c2 (max(f, g))(n). Es gilt also die Additionsregel: F + G ∈ O(max(f, g)). Vorläufige Version 27 c 2002 Peter Thiemann Die Wachstumsordnung auf Funktionen Definition 2 Eine Relation R ⊆ M × M , wobei M Menge, heißt • reflexiv, falls (∀m ∈ M ) m R m; • transitiv, falls (∀m1 , m2 , m3 ∈ M ) m1 R m2 ∧ m2 R m3 ⇒ m1 R m3 ; • symmetrisch, falls (∀m1 , m2 ∈ M ) m1 R m2 ⇔ m2 R m1 ; • Vorordnung, falls R reflexiv und transitiv; • Äquivalenzrelation, falls R reflexiv, transitiv und symmetrisch. Vorläufige Version 28 c 2002 Peter Thiemann Für M = {f | r : N → R+ } definiere f g ⇔ f ∈ O(g) f ≺g ⇔ f ∈ o(g) Es gilt: • ≺ ist transitive Relation • ist Vorordnung • f ≺g⇒f g • Die Relation ≈, definiert durch f ≈ g, falls f g ∧ g f , ist eine Äquivalenzrelation • f ≈ g ⇔ f ∈ Θ(g) Bemerkung: Die Relationen ≺, , ≈ auf Funktionen haben ähnliche Eigenschaften wie <, ≤, = auf Zahlen. Unterschied: Aus f ≈ g folgt nicht f = g! Vorläufige Version 29 c 2002 Peter Thiemann 2.4 Kostenmaße • Programmiersprache statt Turingmaschine • Einheitskostenmaß – Konkrete Maschine hat feste Wortbreite (z.B. 32 Bit); jedes Datenelement belegt gleichen Speicherplatz unabhängig von der Größe – Turingmaschinen für Grundrechenarten, Vergleiche, Kopieren von 32 Bit Zahlen benötigen 32 · c + d Schritte ⇒ eine Konstante unabhängig von der Größe der Zahl ⇒ Aufwand für diese Operationen ist O(1) • logarithmisches Kostenmaß – Jedes Datenelement belegt Platz in Abhängigkeit von seiner Größe – Platzbedarf für Langzahl n in Dualdarstellung: dlog2 n + 1e – Grundrechenarten, Vergleiche, Kopieren benötigen O(dlog2 n + 1e) Schritte Vorläufige Version 30 c 2002 Peter Thiemann 2.5 Kosten für Programmteile Zuweisung: T (x := E) = |E| + 1 ∈ O(1) (E Ausdruck, ohne Funktionsaufrufe; Einheitskostenmaß) Sequenz: T (S1 ; . . . ; Sn ) = T (S1 ) + . . . + T (Sn ) Konditional: Schleife: T (if E S1 S2 ) = T (E) + max(T (S1 ), T (S2 )) Pn T (while E do S) = i=1 Ti (E) + Ti (S) Rekursion: T selbst rekursiv definiert Bemerkung: oft werden nur “wichtige Operationen” gezählt: Vergleiche, Datenbewegungen, usw Vorläufige Version 31 c 2002 Peter Thiemann 2.6 2.6.1 Beispiele Algorithmus Bubble-Sort Sortiert die Zahlen im Array a[1..n] durch wiederholtes Vertauschen. repeat for (i = 1; i < n; i++) if (a[i] > a[i+1]) swap(a, i, i+1) until (keine Vertauschungen mehr notwendig) Abschätzen der Anzahl von Vergleichen: Worst Case: Innere Schleife: n − 1 Vergleiche, maximal n Durchläufe (Minimum an a[n]) der äußeren Schleife ⇒ O(n2 ) Best Case: Array ist bereits sortiert: Ende nach einem Durchlauf ⇒ O(n) Average Case: auch O(n2 ) viele Vergleiche ausgeführt. Vorläufige Version 32 c 2002 Peter Thiemann 2.6.2 Das Maxsummenproblem Problem MaxSum: Betrachte ein Array a[1..n] von ganzen Zahlen. Berechne max{f (i, j) | 1 ≤ i ≤ j ≤ n}, wobei f (i, j) = ai + . . . + aj . Rechenschritte sind arithmetische Operationen und Vergleiche. Naiver Algorithmus Berechne alle Werte von f (i, j) und bestimme dabei das Maximum. m := f (1,1) for (i = 1; i <= n; i++) for (j = i; j <= n; j++) if (f (i,j) > m) m := f (i,j) Die Berechung von f (i, j) benötigt j − i Additionen. Vorläufige Version 33 c 2002 Peter Thiemann Analyse Naiver Algorithmus Es gibt j Paare der Form (·, j) Pn # Vergleiche: V1 (n) = j=1 j ∈ O(n2 ) # Additionen: n X n X A1 (n) = (j − i) i=1 j=i n X n−i X = k i=1 k=1 3 ∈ O(n ) # Rechenschritte: T1 (n) = V1 (n) + A1 (n) ∈ O(n2 ) + O(n3 ) = O(n3 ). Tatsächlich auch Ω(n3 ). Vorläufige Version 34 c 2002 Peter Thiemann 2.6.3 Der etwas bessere Algorithmus Verwende f (i, j + 1) = f (i, j) + aj+1 m := f (1,1) for (i = 1; i <= n; i++) fij := 0 for (j = i; j <= n; j++) fij := fij + a[j] if (fij > m) m := fij Damit braucht man für alle f (i, ·)-Werte genau (n − i + 1) Additionen. # Vergleiche: V2 (n) = V1 (n) ∈ O(n2 ). Pn−1 Pn # Additionen: A2 (n) = i=1 (n − i + 1) = n + k=1 k ∈ O(n2 ). # Rechenschritte: T2 (n) = V2 (n) + A2 (n) ∈ O(n2 ). Vorläufige Version 35 c 2002 Peter Thiemann 2.6.4 Divide-And-Conquer Algorithmusa Zur Lösung von MaxSum auf a[1..n] unterteile die Menge der Index-Paare (i, j) in drei Klassen: 1. 1 ≤ i, j ≤ n/2 MaxSum auf a[1..n/2] 2. 1 ≤ i ≤ n/2 < j ≤ n neues Problem auf a[1..n]! 3. n/2 < i ≤ j ≤ n MaxSum auf a[n/2+1..n] • Die Probleme 1 und 3 sind halb so groß wie das ursprüngliche Problem und werden rekursiv gelöst. • Für Problem 2 setze – g(i) = ai + . . . + an/2 für 1 ≤ i ≤ n/2 – h(j) = an/2+1 + . . . + aj für n/2 < j ≤ n ⇒ f (i, j) = g(i) + h(j) Es gilt: f (i, j) maximal ⇔ g(i) und h(j) maximal a (lat. Vorläufige Version divide et impera) teile und herrsche 36 c 2002 Peter Thiemann • Berechne nacheinander (in n/2 − 1 Additionen) g(n/2) = an/2 g(n/2 − 1) = .. . an/2−1 + an/2 g(1) = a1 + . . . + an/2 und daraus den maximalen Wert von g in (n/2 − 1) Vergleichen. • Berechne den maximalen Wert von h analog. • Damit ergeben sich für das zweite Problem insgesamt n − 1 Additionen und n − 2 Vergleiche, also 2n − 3 Operationen, obwohl die Klasse n2 /4 Paare (i, j) enthält. • Gesamtergebnis aus Lösungen für 1, 2 und 3 durch 2 Vergleiche. Vorläufige Version 37 c 2002 Peter Thiemann Rekursionsgleichung T3 (1) = 0 T3 (n) = 2T3 (n/2) + 2 · n − 3 + 2 Lösungsansatz: Angenommen n = 2k T3 (2k ) = 2T3 (2k−1 ) + 2k+1 − 1 = 4T3 (2k−2 ) + 2k+1 − 2 + 2k+1 − 1 = 8T3 (2k−3 ) + 2k+1 − 4 + 2k+1 − 2 + 2k+1 − 1 = ... = k k−k 2 · T3 (2 )+k·2 k+1 − Pk i=1 2i−1 = 0 + 2k · 2k − 2k + 1 = (2k − 1)2k + 1 Aus n = 2k ergibt sich k = log2 n und somit = (log2 n − 1)n + 1 ∈ Vorläufige Version O(n log n) 38 c 2002 Peter Thiemann 2.6.5 Scanline Algorithmus • MaxSum lässt sich mit einem Durchlauf durch a[1..n] lösen Pj Gesucht: maxsumk = max{ l=i al | 1 ≤ i ≤ j ≤ k} Pk Hilfsgröße: maxtailk = max{ l=i al | 1 ≤ i ≤ k} • Für k = 1 setze maxsum1 = a1 und maxtail1 = a1 . • Für k = 1, . . . , n − 1 setze Pk+1 maxtailk+1 = max{ l=i al | 1 ≤ i ≤ k + 1} Pk = max({ak+1 + l=i al | 1 ≤ i ≤ k} ∪ {ak+1 }) = max(ak+1 + maxtailk , ak+1 ) maxsumk+1 Pj max{ l=i al | 1 ≤ i ≤ j ≤ k + 1} Pj Pk+1 = max({ l=i al | 1 ≤ i ≤ j ≤ k} ∪ { l=i al | 1 ≤ i ≤ k + 1}) = = max(maxsumk , maxtailk+1 ) ⇒ T4 (n) = (n − 1) · 3 = 3n − 3 Operationen Vorläufige Version 39 c 2002 Peter Thiemann 2.6.6 Zusammenstellung der Ergebnisse Naiv: Besser: Divide-and-Conquer: Scanline: T1 (n) ∈ O(n3 ) T2 (n) ∈ O(n2 ) T3 (n) ∈ O(n log n) T4 (n) ∈ O(n) Bemerkung: Es ist möglich, den Scanline Algorithmus aus dem naiven Algorithmus herzuleiten! Vorläufige Version 40 c 2002 Peter Thiemann 2.7 Mastertheorem Gegeben eine Rekursionsgleichung für T : N → R. c T (n) = aT (n/b) + f (n) falls n ≤ d falls n > d. Dabei sind c ≥ 1 und d ≥ 1 natürliche Zahlen, a ≥ 1 und b > 1 reelle Konstanten und f eine reelle Funktion mit f (n) ≥ 0 für n ≥ d. Unterscheide drei Fälle: 1. (∃ > 0) f (n) ∈ O(nlogb a− ) ⇒ T (n) ∈ Θ(nlogb a ) 2. (∃k ≥ 0) f (n) ∈ Θ(nlogb a (log n)k ) ⇒ T (n) ∈ Θ(nlogb a (log n)k+1 ) 3. (∃ > 0) f (n) ∈ Ω(nlogb a+ ) und (∃δ < 1) (n ≥ d) af (n/b) ≤ δf (n) ⇒ T (n) ∈ Θ(f (n)) Vorläufige Version 41 c 2002 Peter Thiemann Beispiele Mastertheorem 1. T (n) = 4T (n/2) + n; a = 4, b = 2, f (n) = n. Mit nlog2 4 = n2 ist T (n) ∈ Θ(n2 ), da Fall 1 gilt: n = f (n) ∈ O(n2− ) für = 1. Genau: T (n) = 2n2 − n 2. T (n) = T (n/2) + 1; a = 1, b = 2, f (n) = 1. Mit nlog2 1 = 1 ist T (n) ∈ Θ(log n), da Fall 2 mit k = 0 gilt. Genau: T (n) = log n + 1 3. T (n) = 2T (n/2) + n log n; a = 2, b = 2, f (n) = n log n. Mit nlog2 2 = n ist T (n) ∈ Θ(n log2 n), da Fall 2 mit k = 1 gilt. Vorläufige Version 42 c 2002 Peter Thiemann 4. T (n) = T (n/3) + n log n; a = 1, b = 3, f (n) = n. Mit nlog3 1 = 1 ist T (n) ∈ Θ(n), da Fall 3 gilt: f (n) = Ω(n0+ ) für = 1 und für δ = 1/3 gilt af (n/b) = (n/3) log(n/3) = (n/3)(log n − log 3) ≤ (n/3) log n = f (n)/3 Vorläufige Version 43 c 2002 Peter Thiemann