Informatik I 1. Kapitel Einführung in Algorithmen und Datenstrukturen Rainer Schrader Zentrum für Angewandte Informatik Köln 16. Juli 2008 1/1 2/1 Einführung in Algorithmen Einführung in Algorithmen Algorithmus Gliederung • Folge von exakten Arbeitsanweisungen • (zum Lösen einer Rechenaufgabe) • in endlich vielen, eindeutig festgelegten, • Algorithmen • Laufzeitanalyse • Laufzeitschranken • Beispiel: das Maximum-Subarray-Problem • auch wiederholbaren Schritten. (ZEIT-Lexikon) 3/1 4/1 Einführung Algorithmen Einführung Algorithmen Algorithmus Programme Rechenvorschrift Eingabe Berechnung • konkrete Formulierungen abstrakter Algorithmen, • die bestimmte Darstellungen und Datenstrukturen verwenden Ausgabe (Wirth) Programmerstellung und Datenstrukturierung sind untrennbare, Jede mit einem Algorithmus lösbare Aufgabe kann prinzipiell auch von einem Rechenautomat gelöst werden. (ZEIT-Lexikon) ineinandergreifende Themen 5/1 6/1 Einführung Einführung Algorithmen Bemerkung zu Programmen Beispiel: Sortierproblem Programme werden in einer abstrahierenden Programmiersprache beschrieben: • Eingabe: Eine Folge von n Zahlen ha1 , a2 , . . . , an i • keine Deklarationen • if-then-else • Ausgabe: Eine Permutation (Umordnung) ha10 , a20 , . . . , an0 i der Eingabefolge, so dass gilt: • for-Schleifen • while-Schleifen • höhere Konstrukte a10 ≤ a20 ≤ . . . ≤ an0 . • Compiler spricht auch deutsch • ... 7/1 8/1 Einführung Algorithmen Einführung Algorithmen • Sortieren ist eine grundlegende Operation in der Informatik • jede konkrete Zahlenfolge ist eine Instanz des Sortierproblems • unterschiedliche Algorithmen erweisen sich je nach Szenario als mehr oder weniger geeignet: • z.B. soll h32, 25, 13, 48, 39i • wie viele Elemente? • kann die Natur der Elemente ausgenützt werden? in • ist schon teilweise sortiert? h13, 25, 32, 39, 48i • im Hauptspeicher, auf Platte? überführt werden • wir wollen versuchen, das jeweilige Verhalten zu analysieren 9/1 10 / 1 Einführung Algorithmen Einführung Algorithmen Spezifikation eines Algorithmus: Sprechweisen: • ein Algorithmus kann auf verschiedene Art und Weise spezifiziert • eine Instanz eines Problems besteht aus allen Eingabewerten, die zur werden: Lösung benötigt werden • auf Deutsch, Englisch, . . . • als Hardwaredesign • ein Algorithmus heißt korrekt, wenn seine Ausführung für jede mögliche Eingabeinstanz mit der korrekten Ausgabe beendet wird • als Computerprogramm (Gegenstand der Informatik I) • ein korrekter Algorithmus löst das gegebene Problem. Wir veranschaulichen den letzten Punkt an einem Sortier-Algorithmus. 11 / 1 12 / 1 Einführung Algorithmen Einführung Algorithmen Sortieren durch Einfügen (insertion sort) Idee: • Sortieren von Spielkarten A[1] A[2] A[3] A[4] A[5] A[6] 5 2 4 6 1 3 2 5 4 6 1 3 2 4 5 6 1 3 2 4 5 6 1 3 1 2 4 5 6 3 1 2 3 4 5 6 • füge das i -te Eingabeelement in die bereits sortierte Liste der ersten i − 1 Elemente ein. 13 / 1 Einführung Algorithmen 1. 2. Einführung Algorithmen • Ablauf auf der Eingabefolge h5, 2, 4, 6, 1, 3i: for j=2 to n do key = A(j) • A(1) A(2) A(3) A(4) A(5) A(6) • 5 2 4 6 1 3 • 5 2 • 2 5 • 2 5 4 • 2 4 5 • 2 4 5 6 • 2 4 5 6 • 1 2 4 5 6 • 2 4 5 6 1 • 1 2 4 5 6 • 1 2 4 5 6 3 • 1 2 3 4 5 6 füge A(j) in die sortierte Folge A(1...j-1) ein 4. i = j - 1 5. 6. 7. while (i > 0 und A(i) > key) do A(i+1) = A(i) i = i-1 end while 8. A(i+1) = key 14 / 1 end do 15 / 1 16 / 1 Einführung Algorithmen Einführung Algorithmen natürliche Fragestellungen an einen Algorithmus: • ist der Algorithmus korrekt? Gliederung • Algorithmen • Laufzeitanalyse • Laufzeitschranken • welche Ressourcen verbraucht der Algorithmus? • logische Schaltungen • Kommunikationsbandbreite • Beispiel: das Maximum-Subarray-Problem • Speicherplatz • Zeit 17 / 1 Einführung Algorithmen 18 / 1 Einführung Algorithmen • wir sind im folgenden fast immer an der Zeit interessiert • aber auf welcher Maschine wird die Zeit verbraucht? • intuitiv am Beispiel des Sortierproblems: • wir betrachten eine idealisierte Maschine: • das Sortieren von 1000 Zahlen dauert länger als das Sortieren von 10 Zahlen, RAM: „random access machine“ • bei gleich langen Folgen geht es für „fast sortierte“ schneller mit folgenden Eigenschaften: • wir beschreiben die Laufzeit als Funktion der Eingabegröße • beim Sortieren als Funktion von n = Anzahl der zu sortierenden Zahlen • 1 Prozessor • alle Daten im Hauptspeicher • die Datenzugriffe dauern alle gleich lange 19 / 1 20 / 1 Einführung Algorithmen Einführung Algorithmen Kosten von insertion_sort • wir zählen die Anzahl der primitiven Operationen (Rechenschritte), • hier vereinfachend: jeder Programmbefehl benötigt konstante Zeit 1.for j=2 to n do 2. key = A(j) füge A(j) ein 3. i = j - 1 4. while(i>0 & A(i)>key) do 5. A(i+1) = A(i) 6. i = i-1 end while 7. A(i+1) = key end do Im Beispiel insertion_sort: • sei tj die Anzahl der Durchläufe der while-Schleife für Index j • entspricht der Anzahl der Positionen, um die Element j verschoben wird Zeile 1 2 3 4 5 6 7 Kosten c1 c2 c3 c4 c5 c6 c7 wie oft? n n−1 n 1 P− n tj j =2 Pn (t − 1) Pjn=2 j (t j =2 j − 1) n−1 21 / 1 22 / 1 Einführung Algorithmen Zeile 1 2 3 4 5 6 7 Kosten c1 c2 c3 c4 c5 c6 c7 Einführung Algorithmen wie oft? n n−1 n 1 P− n t Pnj =2 j (t − 1) Pnj =2 j (t j =2 j − 1) n−1 Bester Fall: Die Eingabefolge ist bereits sortiert • in Zeile 4 ist dann immer A(i) ≤ key • somit tj = 1 für j = 2, 3, . . . n, deshalb T (n) = c1 n + c2 (n − 1) + c3 (n − 1) + c4 n X (tj − 1) + c7 (n − 1) + c6 Gesamtlaufzeit: n X j =2 tj + c5 n X (tj − 1) j =2 j =2 T (n) = c1 n + c2 (n − 1) + c3 (n − 1) + c4 n X = c1 n + c2 (n − 1) + c3 (n − 1) + c4 (n − 1) + c7 (n − 1) tj = (c1 + c2 + c3 + c4 + c7 )n − (c2 + c3 + c4 + c7 ) j =2 + c5 n X j =2 (tj − 1) + c6 n X = an + b (tj − 1) + c7 (n − 1) für Konstanten a und b, ; lineare Funktion in n. j =2 23 / 1 24 / 1 Einführung Algorithmen Einführung Algorithmen Schlechtester Fall: Die Eingabefolge ist in umgekehrter Reihenfolge sortiert. • hier gilt tj = j für j = 2, 3, . . . , n, deshalb T (n) = c1 n + c2 (n − 1) + c3 (n − 1) + c4 n X + c6 (tj − 1) + c7 (n − 1) n X tj + c5 j =2 worst-case Laufzeit n X (tj − 1) • die längste mögliche Laufzeit bei vorgegebener Eingabegröße der j =2 Instanz, • eine obere Schranke für die Laufzeit einer beliebigen Instanz dieser j =2 „ « „ « n(n + 1) n(n − 1) − 1 + c5 2 2 Größe = c1 n + c2 (n − 1) + c3 (n − 1) + c4 « „ n(n − 1) + c6 + c7 (n − 1) 2 “c ” “ ” c4 c5 c6 c5 c6 4 n 2 + c1 + c2 + c3 + = + + − − + c7 n 2 2 2 2 2 2 − (c2 + c3 + c4 + c7 ) = an 2 + bn + c Bei manchen Problemen kann der „worst-case“ oft auftreten, z.B. bei der Suche eines nicht vorhandenen Eintrags in einer Datenbank. für Konstanten a, b und c, ; quadratische Funktion in n. 25 / 1 26 / 1 Einführung Algorithmen Einführung Algorithmen average-case Laufzeit • ist die durchschnittliche Laufzeit über alle Instanzen der Größe Vereinfachung n (einer gegebenen Instanzklasse), • wir werden uns von der mühsamen Berechnung der Konstanten frei • kann manchmal erheblich besser als der worst case sein machen • wir werden nur die Ordnung der Laufzeit betrachten, also • kann aber auch genauso schlecht wie der worst case sein • (beim Sortieren durch Einfügen führt tj = 2j auch zu einer an 2 + bn + c = Θ(n 2 ) quadratischen Laufzeitfunktion T (n).) an + b = Θ(n) • das Problem beim average case ist: • darauf gehen wir später präziser ein Was ist eine durchschnittliche Eingabe? 27 / 1 28 / 1 Einführung Algorithmen Einführung Algorithmen • Sortieren durch Einfügen benutzt inkrementellen Ansatz • ein anderer Ansatz ist Sortierung durch Verschmelzen (merge sort) „teile und erobere“ – „divide and conquer“ • teile: teile die n-elementige Folge in der Mitte in zwei Teilfolgen, • erobere: sortiere beide Teilfolgen rekursiv mit merge sort, • teile das Problem in Teilprobleme auf • kombiniere: verschmelze die beiden Teilfolgen zu einer sortierten • erobere die Teilprobleme durch rekursives Lösen (wenn sie klein Gesamtfolge genug sind, löse sie direkt) • kombiniere die Lösungen der Teilprobleme zu einer Lösung des Bemerkung: Für einelementige Teilfolgen ist nichts zu tun. Gesamtproblems Wir veranschaulichen diesen Ansatz wiederum an einem Sortieralgorithmus. 30 / 1 29 / 1 Einführung Algorithmen Einführung Algorithmen Grobkonzept von merge sort merge_sort • A : Array • p ,q, r : Indizes mit p ≤ q ≤ r . merge_sort(A,p,r) if (p < r) then do • merge(A,p,q,r) • verschmilzt die beiden bereits sortierten Teilarrays A(p..q) und A(q+1..r) q = (p+r)/2 merge_sort(A,p,q) merge_sort(A,q+1,r) merge(A,p,q,r) • ; sortiertes Array A(p..r) • Laufzeit beträgt Θ(r − p + 1) (Übungsaufgabe) • merge_sort(A,p,r) end if • sortiert A(p..r) end • falls p ≥ r gilt, so ist nichts zu tun • Sortieren eines n-elementigen Arrays durch merge_sort(A,1,n). 31 / 1 32 / 1 Einführung Algorithmen Einführung Algorithmen Illustration: Analyse der worst-case-Laufzeit Vereinfachende Annahme: n = 2k für k ≥ 1. Eingabefolge 5 2 4 6 1 3 2 6 2 5 4 6 1 3 2 6 2 4 5 6 1 2 3 6 1 2 2 3 4 5 6 6 • gesucht: Laufzeit T (n). • Teile: Bestimmung der Mitte des Arrays in konstanter Zeit D(n) = c1 . • Erobere: Lösen zweier Teilprobleme der Größe n2 in 2T ( n2 ) Zeit. • Kombiniere: wie diskutiert C(n) = c2 n. • insgesamt: T (n) ≤ c 2T ( n2 ) + cn für n = 1 für n > 1 • mit c = max{c1 , c2 }. Ausgabefolge Behauptung: T (n) ≤ cn log2 n + cn und damit besser als Sortieren durch Einfügen. 33 / 1 34 / 1 Einführung Algorithmen Einführung Algorithmen Bedeutung in der Praxis Behauptung: T (n) ≤ cn log2 n + cn = cn log n + cn . • Wettbewerb im Sortieren von 80.000.000 Zahlen Beweis per Induktion: T (1) ≤ c = c · 1 · 0 + c · 1 = c · 1 log2 1 + c · 1 • 2 Teilnehmer: √ • ein Hochleistungsrechner mit einem schlechten Programm • ein PC mit einem guten Programm n T (n) ≤ 2T ( ) + cn 2 n n n ≤ 2[c log + c ] + cn 2 2 2 n = cn log + 2cn 2 = cn log n − cn log 2 + 2cn = cn log n − cn + 2cn = cn log n + cn (per Induktion) Supercomputer Algorithmus Implementierung Geschwindigkeit insertion_sort 2n 2 1012 Op./s (1 Teraflop) merge_sort 50n log2 n 109 Op./s (1 Gigaflop) √ PC Damit folgt: T (n) ≤ cn log n + cn. 35 / 1 36 / 1 Einführung Algorithmen Algorithmus Supercomputer PC insertion_sort merge_sort Implementierung 2 2n 50n log2 n Einführung Algorithmen Geschwindigkeit 12 10 Op./s (1 Teraflop) 109 Op./s (1 Gigaflop) Gliederung Zeitbedarf: • Algorithmen • Laufzeitanalyse • Laufzeitschranken • Supercomputer: 2 · (8 · 107 )2 Operationen = 12800 sec ≈ 3.5 h 1012 Operationen/sec • PC: • Beispiel: das Maximum-Subarray-Problem 50 · 8 · 107 · log2 (8 · 107 ) Operationen ≈ 105 sec 109 Operationen/sec. Wie Hardware sind auch Algorithmen Technologie 37 / 1 38 / 1 Einführung Algorithmen Einführung Algorithmen Sei g : N0 → R eine Funktion. Wir definieren die folgenden Mengen von Funktionen: Wir wollen das qualitative Wachstum der Laufzeit eines Algorithmus ausdrücken: • sei dazu f : N0 → R die Laufzeitfunktion • O(g(n)) := {f (n) : f (n) ≤ cg(n)} • sei g : N0 → R eine Vergleichsfunktion für alle n ≥ n0 . • Ω(g(n)) := {f (n) : cg(n) ≤ f (n)} für alle n ≥ n0 . • wir wollen ausdrücken: • Θ(g(n)) := {f (n) : cg(n) ≤ f (n) ≤ dg(n)} • f wächst höchstens so schnell wie g • f wächst mindestens so schnell wie g für alle n ≥ n0 . jeweils für geeignete Konstanten c, d , n0 > 0 (genauer: zu jedem • f wächst wie g f existieren Konstanten …). 39 / 1 40 / 1 Einführung Algorithmen Einführung Algorithmen Illustration: Schreibweise: • anstelle von f (n) ∈ Θ(g(n)) schreiben wir c2 g(n) f (n) = Θ(g(n)) f(n) • entsprechend f (n) = Ω(g(n)) und f (n) = O(g(n)) c1 g(n) • wir benutzen die Notationen • O für obere Schranken, • Ω für untere Schranken, • Θ für die „genaue“ Bestimmung der Wachstumsrate. n n0 41 / 1 42 / 1 Einführung Algorithmen Einführung Algorithmen Beispiel: Beispiel: 1 2 n − 3n = Θ(n 2 ). 2 6n 3 6= Θ(n 2 ) zu zeigen: Annahme: es gibt Konstanten c2 , n0 , so dass • es existieren Konstanten c1 , c2 und n0 , • so dass c1 n 2 ≤ 12 n 2 − 3n ≤ c2 n 2 für alle n ≥ n0 . (1) Mit Division durch n 2 > 0 erhalten wir c1 ≤ (1) gilt für alle n ≥ 7, wenn c1 ≤ (2) gilt für alle n ≥ 1, wenn c2 ≥ Also wähle z.B. c1 = 1 , 14 c2 = 1 2 1 2 − 3 n Dann folgt: n ≤ c2 6 für alle n ≥ n0 6n 3 ≤ c2 n 2 für alle n ≥ n0 . Allgemein gilt: (2) ≤ c2 . an 2 + bn + c = Θ(n 2 ). 1 . 14 1 . 2 Beweis als Übungsaufgabe. und n0 = 7. 43 / 1 44 / 1 Einführung Algorithmen Einführung Algorithmen Beispiel: insertion_sort: • worst case Laufzeit O(n 2 ): Beispiel • ergibt sich aus der Doppelschleife Für jede Konstante c gilt: c = Θ(1). • impliziert Laufzeit von O(n 2 ) für beliebige Eingaben zu zeigen: • die worst case Laufzeit Θ(n 2 ) impliziert nicht eine Laufzeit Θ(n 2 ) für • es existieren Konstanten c1 , c2 und n0 , • so dass c1 · 1 ≤ c ≤ c2 · 1 für alle n ≥ n0 . beliebige Eingaben: • ist die Eingabe bereits sortiert: Laufzeit Θ(n) wähle c1 = c2 = c und n0 = 1. • eine best case Laufzeit Ω(n) impliziert eine Laufzeit Ω(n) für beliebige Eingaben. 46 / 1 45 / 1 Einführung Algorithmen Einführung Algorithmen Weitere Schreibweisen: Beispiel Beispiel 2n 2 + Θ(n) = Θ(n 2 ) 2n 2 + 3n + 1 = 2n 2 + Θ(n) Interpretation: Interpretation: • für alle f (n) ∈ Θ(n) existiert ein g(n) ∈ Θ(n 2 ) so, • dass 2n 2 + f (n) = g(n) für alle n • es gibt eine Funktion f (n) ∈ Θ(n) mit • 2n 2 + 3n + 1 = 2n 2 + f (n) • (wähle g(n) = 2n 2 + f (n)). • (wähle f (n) = 3n + 1). 47 / 1 48 / 1 Einführung Algorithmen Einführung Algorithmen Um von einem speziellen Computer unabhängig zu sein, zählen wir Entwarnung: wir werden fast auschließlich Elementaroperationen: • obere Schranken berechnen • Zuweisungen a = b, • arithmetische Befehle a = b ◦ c mit ◦ ∈ {+,-,*,/,%,. . .}, • logische Operationen und, oder, neg, . . . und • einfache Funktionen dafür verwenden: O(n), O(n 2 ), O(n 3 ), …, O(n k ) • O(n log n), O(n 2 log n), … • • Sprungbefehle • goto label; • if a ∝ b . . .; else . . .; mit ∝∈ { <, <=, ==, !=, >=, >} 50 / 1 49 / 1 Einführung Algorithmen Einführung Algorithmen for- und while-Schleifen Vereinfachende Annahme • if <Bedingung> <Anweisung1> else <Anweisung2> • • jede Elementaroperation benötigt eine Zeiteinheit Kosten := • wir vernachlässigen also: • die Indexrechnungen, • den Typ der Operanden und Kosten(Bedingung) + Kosten(Anweisung1) Kosten(Bedingung) + Kosten(Anweisung2) • while <Bedingung> <Anweisung> • for <Schleife> do <Anweisung> end do • die Länge der Operanden • Kosten: die wiederholten Kosten für Test auf Bedingung bzw. Schleifenende und (1× weniger) die Kosten der Anweisung. 51 / 1 52 / 1 Einführung Algorithmen Einführung Algorithmen Maximum-Subarray-Problem • gegeben: eine Folge von n ganzen Zahlen in einem Array • gesucht: • eine zusammenhängenden Teilfolge, Gliederung • deren Summe maximal ist. • Algorithmen • Laufzeitanalyse • Laufzeitschranken • (Die Teilfolge kann auch leer sein.) • Beispiel: das Maximum-Subarray-Problem Beispiel: 31 − 41 59 26 − 53 58 97 − 93 − 23 84 31 − 41 − 53 58 97 {z } −93 − 23 84 59 26 | Wert 187 ist maximal. 53 / 1 54 / 1 Einführung Algorithmen Einführung Algorithmen 1. Versuch: naiver Ansatz 1. Versuch: naiver Ansatz 31 • berechne für jedes Teilintervall die Summe der Einträge −41 59 26 −53 58 97 −93 −23 84 • unter all diesen Summen wähle das Maximum 55 / 1 56 / 1 Einführung Algorithmen Einführung Algorithmen 1. Versuch: naiver Ansatz Laufzeitanalyse des naiven Ansatzes maxteilsumme = 0 n X n X r X T (n) = for li = 1 to n do for re = li to n do 1 `=1 r =` i =` n n X X (r − ` + 1) = // bestimme Summe in der Teilfolge X[li,...,re] summe = 0 for i = li to re do summe = summe + X(i) end do // schreibe Maximum fort if (summe > maxteilsumme) maxteilsumme = summe end do `=1 r =` n n−`+1 X X = `=1 i i =1 n X 1 (n − ` + 1)(n − ` + 2) 2 = `=1 = Θ(n 3 ) end do return maxteilsumme 57 / 1 58 / 1 Einführung Algorithmen Einführung Algorithmen Versuch 1a: ein etwas weniger naiver Ansatz maxteilsumme = 0 Versuch 1a: ein etwas weniger naiver Ansatz for li = 1 to n do summe = 0 for re = li to n do summe = summe + X(i) // schreibe Maximum fort if (summe > maxteilsumme) maxteilsumme = summe end do end do • wir berechnen die Intervallsumme stets neu • sie kann jedoch einfach fortgeschrieben werden • dies reduziert die Laufzeit auf O(n 2 ) return maxteilsumme 59 / 1 60 / 1 Einführung Algorithmen Einführung Algorithmen 2. Versuch: Divide and Conquer • wird die Folge in der Mitte geteilt, so gilt für eine maximale Teilfolge MT : 2. Versuch: Divide and Conquer (1) entweder liegt MT ganz in einem der beiden Teile • wir verwenden zwei Prozeduren: (2) oder MT umfasst die Trennstelle. • rightmax(X , `, r ) berechnet im Intervall [`, r ] eine maximale Teilfolge, die ` enthält • sei MT = (`, . . . , re) • sei m der mittlere Index • leftmax(X , `, r ) berechnet im Intervall [`, r ] eine maximale Teilfolge, die r enthält • im Fall (2) gilt : • (`, . . . , m) ist eine größte Teilfolge im linken Intervall, die m enthält • (m, . . . , re) ist eine größte Teilfolge im rechten Intervall, die m enthält 61 / 1 62 / 1 Einführung Algorithmen Einführung Algorithmen Divide-and-conquer Bestimmung des rechten Maximums in (`..r ) procedure msp2(X,le,re) if re = le then teilmax = X(le) else do // halbiere Intervall m = (le+re)/2 procedure rightmax(X,le,re) rmax = 0 summe = 0 for i = le to re do summe = summe + X(i) if (summe > rmax) rmax = summe end do return rmax end procedure mtsl = msp2(X,le,m) mtsr = msp2(X,m+1,re) // berechne das Maximum im // linken und rechten Intervall lmax = leftmax(X,le,m) // bestimme linke Teilfolge rmax = rightmax(m,re) // bestimme rechte Teilfolge teilmax = maximum {mtsl, mtsr, lmax+rmax-X(m)} end if return teilmax end procedure • benötigt Θ(r − `) Zeit • leftmax(X , `, r ) analog 63 / 1 64 / 1 Einführung Algorithmen Einführung Algorithmen wir wissen: T (n) ≤ Sei T (n) die worst-case-Laufzeit. Dann gilt: T (n) = Θ(1) `¨ ˝´ `˚ ˇ´ T n2 + T n2 + Θ(n) a `˚ ˇ´ `¨ ˝´ T n2 + T n2 + an für n = 1 für n > 1 für n = 1 für n > 1 • wir zeigen per Induktion: • für n ≥ 3 und c = 3a gilt Satz Für die obige Rekursion gilt T (n) = Θ(n log2 n). T (n) ≤ cn log(n − 1) Beweis: • wir zeigen T (n) = O(n log2 n) • es gilt auch T (n) = Ω(n log2 n) • die Fälle n = 3, 4, 5 zeigt man explizit • wir führen nur den allgemeinen Fall n ≥ 6 vor (Übungsaufgabe) 65 / 1 66 / 1 Einführung Algorithmen Einführung Algorithmen der Fall n = 3 : der Fall n = 4 : T (3) ≤ T (1) + T (2) + 3a (da T (2) ≤ T (1) + T (1) + 2a) T (4) ≤ T (2) + T (2) + 4a ≤ 3T (1) + 5a ≤ 8a (da T (1) ≤ a) 8 = c 3 ≤ 3c (da c = 3a) ≤ 4T (1) + 8a (da T (2) ≤ 2T (1) + 2a) ≤ 12a (da T (1) ≤ 3a) = 4c (da c = 3a) ≤ c · 4 · log 3 = c · 3 · log(3 − 1) somit gilt für n = 4 : Somit gilt für n = 3: T (n) ≤ cn log(n − 1). entsprechend für n = 5 : T (n) ≤ 3n log(n − 1). 67 / 1 T (n) ≤ cn log(n − 1). 68 / 1 Einführung Algorithmen Einführung Algorithmen Der Fall n ≥ 6 : T (n) ≤ T ≤c “l n m” 2 ln m 2 log +T 2 ” jn k “j n k ” −1 +c log − 1 + an (per Induktion) 2 2 2 n+1 log 2 n+1 =c log 2 „ = 1 1 n+1 n c(n + 1) log(n − 1) + cn log(n − 2) − c − c + an 2 2 2 2 ≤ 1 1 n+1 n c(n + 1) log(n − 1) + cn log(n − 1) − c − c + an 2 2 2 2 ≤ 1 1 1 c cn log(n − 1) + c log(n − 1) + cn log(n − 1) − cn − + an 2 2 2 2 + an “l n m „ ≤c “j n k” « “n ” n+1 n − 1 + c log − 1 + an (Monotonie von log) 2 2 2 = cn log(n − 1) + n−1 2 « n + c log 2 „ n−2 2 « c c c log(n − 1) − cn − + n 2 2 3 (da c = 3a) + an c c (2n + 1 − log(n − 1)) + n 2 2 c c ≤ cn log(n − 1) − (2n + 1 − log(n − 1)) + n 2| {z } 2 ≤ cn log(n − 1) − = 1 1 n+1 n c(n + 1) log(n − 1) + cn log(n − 2) − c − c + an 2 2 2 2 (≥n) 69 / 1 70 / 1 Einführung Algorithmen ≤ cn log(n − 1) − Einführung Algorithmen c c (2n + 1 − log(n − 1)) + n 2| {z } 2 (≥n) ≤ cn log(n − 1) − Wir haben bisher: c c n+ n 2 2 • trivialer Ansatz: O(n 3 ) • etwas weniger trivialer Ansatz: O(n 2 ) = cn log(n − 1) • 2. Ansatz: O(n log n) Ist dies bestmöglich? 71 / 1 72 / 1 Einführung Algorithmen Einführung Algorithmen 3. Versuch: • sei lmaxi der Wert einer maximalen Teilsumme mit fester rechter Grenze i • wobei die leere Folge ∅ zugelassen ist • sei bismaxi der maximale Wert im Intervall [1, . . . , i ] i bismax lmax es gilt: i • lmaxi +1 = lmax bismax lmaxi + X (i + 1), 0, falls lmaxi + X (i + 1) > 0 falls lmaxi + X (i + 1) ≤ 0 • bismaxi +1 = max{bismaxi , lmaxi +1 } 73 / 1 74 / 1 Einführung Algorithmen Einführung Algorithmen Scanline-Ansatz msp3(X, n) lmax = 0 bismax = 0 for i=1 to n do a = X(i) Aktualisierung if (lmax + a > 0) lmax = lmax + a else lmax = 0 end if if (lmax > bismax) bismax = lmax end do return bismax 3. Versuch: „Scan Line Prinzip“ Idee: • durchlaufe das Array von links nach rechts • in Position i aktualisiere: • bismax • lmax 75 / 1 76 / 1 Einführung Algorithmen Skizze: Scanline vorher nachher a bismax lmax • offensichtlich: T (n) = O(n) • jeder MSP-Algorithmus benötigt wenigstens n Schritte • ; der scanline-Ansatz ist optimal (bis auf Konstanten) 77 / 1