Prof. Dr. Margarita Esponda

Ähnliche Dokumente
Prof. Dr. Margarita Esponda

Funktionale Programmierung ALP I. Die Natur rekursiver Funktionen SS Prof. Dr. Margarita Esponda. Prof. Dr.

Algorithmen und Datenstrukturen 1 Kapitel 5

Funktionale Programmierung ALP I. Funktionen höherer Ordnung. Teil 2 SS Prof. Dr. Margarita Esponda. Prof. Dr.

ALP I. Funktionale Programmierung

Objektorientierte Programmierung VL: Prof. Dr. Marco Block-Berlitz - Freie Universität Berlin Proinformatik III

Übung Algorithmen und Datenstrukturen

Prof. Dr. Margarita Esponda

3.3 Laufzeit von Programmen

Komplexität von Algorithmen

Komplexität von Algorithmen:

Asymptotik und Laufzeitanalyse

Babeș-Bolyai Universität Cluj Napoca Fakultät für Mathematik und Informatik Grundlagen der Programmierung MLG5005. Rekursion

2. Grundlagen. Beschreibung von Algorithmen durch Pseudocode. Korrektheit von Algorithmen durch Invarianten.

2. Effizienz von Algorithmen

Komplexität von Algorithmen

2. Algorithmen und Algorithmisierung Algorithmen und Algorithmisierung von Aufgaben

Komplexität von Algorithmen OOPM, Ralf Lämmel

Kapitel 6. Komplexität von Algorithmen. Xiaoyi Jiang Informatik I Grundlagen der Programmierung

Abgabe: (vor der Vorlesung) Aufgabe 2.1 (P) O-Notation Beweisen Sie die folgenden Aussagen für positive Funktionen f und g:

WS 2009/10. Diskrete Strukturen

Algorithmen und Datenstrukturen Effizienz und Funktionenklassen

Grundlagen der Programmierung 2. Sortierverfahren

3.2. Korrektheit und Komplexität am Beispiel: Sortieren Sortieren ist eine wichtige Basis-Operation für komplexe Algorithmen

Lösungsvorschlag Serie 2 Rekursion

Algorithmen und Datenstrukturen I Grundlagen

Komplexität. G. Zachmann Clausthal University, Germany Leistungsverhalten von Algorithmen

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

Die Korrektheit von Mergesort

Programmiertechnik II

Übung zur Vorlesung Berechenbarkeit und Komplexität

Kapitel 3 Zur Korrektheit und Effizienz von Algorithmen

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

2 Wachstumsverhalten von Funktionen

1. Asymptotische Notationen 2. Zahlentheoretische Algorithmen 3. Sortierverfahren 4. String Matching 5. Ausgewählte Datenstrukturen

Algorithmen und Datenstrukturen 1-1. Seminar -

( )= c+t(n-1) n>1. Stand der Vorlesung Komplexität von Algorithmen (Kapitel 3)

Grundlagen: Algorithmen und Datenstrukturen

Alle bislang betrachteten Sortieralgorithmen hatten (worst-case) Laufzeit Ω(nlog(n)).

Laufzeit und Komplexität

Informatik I Komplexität von Algorithmen

Stand der Vorlesung Komplexität von Algorithmen (Kapitel 3)

Kostenmodell. Daniel Graf, Tobias Pröger. 22. September 2016 (aktualisierte Fassung 5 vom 9. Oktober 2016)

Praktische Informatik I - Algorithmen und Datenstrukturen Wintersemester 2006/ Algorithmen und ihre formalen Eigenschaften, Datenstrukturen

Suchen und Sortieren

Informatik I Komplexität von Algorithmen

11. Rekursion, Komplexität von Algorithmen

Master-Veranstaltung Funktionale Programmierung. Effizienz. Wintersemester 2007/2008 Kim Kirchbach (Inf6310) Mirco Schenkel (Inf6311)

Informatik II. Vorlesung am D-BAUG der ETH Zürich. Felix Friedrich & Hermann Lehner FS 2018

2. Hausübung Algorithmen und Datenstrukturen

Isomorphismus. Definition Gruppen-Isomorphismus. Seien (G, +) und (G, ) Gruppen. Die Abbildung f : G G heißt Gruppen-Isomorphismus, falls gilt

Sortieren durch Einfügen (Insertion Sort) fügt die restlichen Elemente nach und nach in die bereits sortierte Liste der abgearbeiteten Zahlen.

Algorithmen und Datenstrukturen (für ET/IT)

lim log 2n n = > 0 Da es einen Limes gibt, gibt es auch einen Limes inferior, der gleich diesem Limes ist.

2.2 Allgemeine (vergleichsbasierte) Sortierverfahren

WS 2011/2012. RobertGiegerich. November 12, 2013

Einführung in die Informatik I

Heapsort / 1 A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

2. Algorithmische Methoden 2.1 Rekursion. 18. April 2017

WS 2011/2012. RobertGiegerich. November 12, 2013

8 Komplexitätstheorie

ALP I Induktion und Rekursion

Informatik II. Algorithmen und Datenstrukturen. Vorläufige Version 1 c 2002 Peter Thiemann

Algorithmen und Datenstrukturen 1 Kapitel 4

Algorithmen und Datenstrukturen

Datenstrukturen & Algorithmen

Exponentiation: das Problem Gegeben: (multiplikative) Halbgruppe (H, ), Element a H, n N Aufgabe: berechne das Element

Informatik II. 1. Einführung. Ziele der Vorlesung. Inhalte der Vorlesung. Vorlesung am D-BAUG der ETH Zürich

Datenstrukturen und Algorithmen

4 Effizienz und Komplexität 3.1 1

Grundlagen der Programmierung

Algorithmik Übung 2 Prof. Dr. Heiner Klocke Winter 11/

Typdeklarationen. Es gibt in Haskell bereits primitive Typen:

INFORMATIK FÜR BIOLOGEN

Datenstrukturen, Algorithmen und Programmierung 2

Grundlagen der Programmierung 2 (1.B)

Ordnen Sie die folgenden Funktionen nach ihrer asymptotischer Komplexität in aufsteigender Reihenfolge: i=1 4i + n = 4 n. i=1 i + 3n = 4 ( n(n+1)

Übung Algorithmen I

es gibt Probleme, die nicht berechenbar sind (z.b. Menge aller Funktionen N N und die Menge aller Sprachen sind überabzählbar)

Programmierung 1 (Wintersemester 2012/13) Lösungsblatt 10 (Kapitel 11)

Einführung in die Funktionale Programmierung mit Haskell

Tutoraufgabe 1 (Auswertungsstrategie):

Algorithmen und Datenstrukturen (ESE) Entwurf, Analyse und Umsetzung von Algorithmen (IEMS) WS 2014 / 2015 Vorlesung 3, Donnerstag 6.

Algorithmen und Datenstrukturen

Algorithmen und Datenstrukturen

Übungsblatt 1. f(n) = f(n) = O(g(n)) g(n) = O(f(n)) Zeigen oder widerlegen Sie: 3 n = Θ(2 n ) Aufgabe 1.2 Gegeben sei die folgende Funktion:

Was bisher geschah. deklarative Programmierung. funktionale Programmierung (Haskell):

Algorithmen und Datenstrukturen Heapsort

Algorithmenbegriff: Berechenbarkeit. Algorithmenanalyse. (Berechnung der Komplexität)

f 1 (n) = log(n) + n 2 n 5 f 2 (n) = n 3 + n 2 f 3 (n) = log(n 2 ) f 4 (n) = n n f 5 (n) = (log(n)) 2

8. Sortieren II. 8.1 Heapsort. Heapsort. [Max-]Heap 6. Heapsort, Quicksort, Mergesort. Binärer Baum mit folgenden Eigenschaften

Grundlagen der Programmierung 2 (1.B)

5. Übungsblatt zu Algorithmen II im WS 2017/2018

Funktionale Programmierung mit Haskell

UE Algorithmen und Datenstrukturen 1 UE Praktische Informatik 1. Übung 5. Asymptotische Laufzeitkomplexität Definition Regeln Beispiele

Kapitel 5: Paradigmen des Algorithmenentwurfs. Gliederung

Gliederung. Algorithmen und Datenstrukturen I. Listen in Haskell: Listen in Haskell: Listen in Haskell. Datentyp Liste Strings Listenkomprehension

4. Sortieren 4.1 Vorbemerkungen

Achtung: Groß O definiert keine totale Ordnungsrelation auf der Menge aller Funktionen! Beweis: Es gibt positive Funktionen f und g so, dass

Algorithmen und Datenstrukturen Laufzeitabschätzung

Transkript:

Analyse von Algorithmen Die O-Notation WS 2012/2013 Prof. Dr. Margarita Esponda Freie Universität Berlin 1

Korrekte und effiziente Lösung von Problemen Problem Wesentlicher Teil der Lösung eines Problems. Sehr kreative Phase Algorithmus Programmierung oder Codierung des Algorithmus in einer bestimmten Programmiersprache. Programm in einer höheren Programmiersprache Einfache Phase 2

Analyse von Algorithmen Korrektheit Wichtigste Eigenschaften bei der Analyse von Algorithmen Terminierbarkeit Rechenzeit Komplexität Speicherplatz Bandbreite oder Datentransfer 3

Analyse von Algorithmen Rechenzeit Anzahl der durchgeführten Elementaroperationen in Abhängigkeit von der Eingabegröße. Speicherplatz Maximaler Speicherverbrauch während der Ausführung des Algorithmus in Abhängigkeit von der Komplexität der Eingabe. Bandbreite Wie groß ist die erforderliche Datenübertragung. 4

Analyse von Algorithmen Charakterisierung unserer Daten (Eingabegröße) Bestimmung der abstrakten Operationen Zeitanalyse (Berechnungsschritte in unserem Algorithmus) Eigentliche mathematische Analyse, um eine Funktion in Abhängigkeit der Eingabegröße zu finden. Komplexitätsanalyse 5

Eingabedaten Zuerst müssen wir unsere Eingabedaten charakterisieren. Meistens ist es sehr schwer eine genaue Verteilung der Daten zu finden, die dem realen Fall entspricht. Deswegen müssen wir in der Regel den schlimmsten Fall betrachten und auf diese Weise eine obere Schranke für die Laufzeit finden. Wenn diese obere Schranke korrekt ist, garantieren wir, dass -für beliebige Eingabedaten- die Laufzeit unseres Algorithmus immer kleiner oder gleich dieser Schranke ist. Beispiel: Die Anzahl der Objekte, die wir sortieren wollen Die Anzahl der Listen, die wir verarbeiten wollen u.s.w. 6

Die zu messenden Operationen Der zweite Schritt unserer Analyse ist die Bestimmung der abstrakten Operationen, die wir messen wollen. D.h., Operationen, die mehrere kleinere Operationen zusammenfassen, welche einzeln in konstanter Zeit ausgeführt werden, aber den gesamten Zeitaufwand des Algorithmus durch ihr häufiges Vorkommen wesentlich mitbestimmen. 7

Die zu messenden Operationen Beispiel: Bei Sortieralgorithmen messen wir Vergleiche Bei Algorithmen in imperativen Sprachen: Speicherzugriffe Anzahl der Multiplikationen Anzahl der Bitoperationen Anzahl der Schleifen-Durchgänge Anzahl der Funktionsaufrufe u.s.w. In Funktionalen Programmiersprachen Anzahl der Reduktionen 8

Die eigentliche Analyse Hier wird eine mathematische Analyse durchgeführt, um die Anzahl der Operationen zu bestimmen. Das Problem besteht darin, die beste obere Schranke zu finden, d.h. eine Schranke, die tatsächlich erreicht wird, wenn die ungünstigsten Eingabedaten vorkommen. (worst case). Die meisten Algorithmen besitzen einen Hauptparameter N, der die Anzahl der zu verarbeitenden Datenelemente angibt. Die obere Schranke ist eine Funktion, die das Wachstum der Laufzeit in Abhängigkeit der Eingabegröße beschreibt. Oft ist es für die Praxis sehr nützlich, den mittleren Fall zu finden, aber meistens ist diese Berechnung sehr aufwendig. 9

Summe und Multiplikation in der Schule Summe n Eingabegröße: 1 2 2 2 2 2 2 2 2 2 2 2 1 n = Zahlenbreite * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Berechnungsschritt: Addition von zwei Ziffern * * * * * * * * * * * * Komplexitätsanalyse: T(n) = Anzahl der Berechnungsschritte, um zwei Zahlen mit n Im schlimmsten Fall: Ziffern zu addieren T(n) = 2n T(n) ist eine lineare Funktion 10

Multiplikation n x * * * * * * * * * * * * * * n 2 Eingabegröße: n = Anzahl der Ziffern n 2 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * n n n n n n n Berechnungsschritt: Multiplikation von zwei Ziffern Komplexitätsanalyse: T(n) = n 2 Im schlimmsten Fall Multiplikation und Addition von Ziffern keine Nullen T(n) = n 2 + cn 2 = (1+c) n 2 = an 2 immer ein Übertrag T(n) ist eine quadratische Funktion 11

Zeit Summe und Multiplikation Ab einem bestimmten Summe T(n)=cn n 0 gilt cn < an 2 T(n)=an 2 Multiplikation n 0 n 12

O-Notation Für die Effizienzanalyse von Algorithmen wird eine spezielle mathematische Notation verwendet, die als O-Notation bezeichnet wird. Die O-Notation erlaubt es, Algorithmen auf einer höheren Abstraktionsebene miteinander zu vergleichen. Algorithmen können mit Hilfe der O-Notation unabhängig von Implementierungsdetails, wie Programmiersprache, Compiler und Hardware-Eigenschaften, verglichen werden. 13

Definition: Die Funktion T(n) = O(g(n)), wenn es positive Konstanten c und n 0 gibt, so dass T(n) c. g(n) für alle n n 0 Zeit c. g(n) T(n) n n 0 14

Bedeutung der O-Notation Wichtig ist, dass O(n 2 ) eine Menge darstellt, weshalb die Schreibweise 2n + n 2 O(n 2 ) besser ist als die Schreibweise n 2 + 2n = O(n 2 ) n 2 beschreibt die allgemeine Form der Wachstumskurve n 2 + 2n = O(n 2 ) Bedeutet nicht "=" im mathematischen Sinn deswegen darf man die Gleichung nicht drehen! O(n 2 ) = n 2 + 2n FALSCH! 15

Eigenschaften der O-Notation Die O-Notation betont die dominante Größe Beispiel: Größter Exponent 3n 3 + n 2 + 1000n + 500 = O(n 3 ) Ignoriert Proportionalitätskonstante Ignoriert Teile der Funktion mit kleinerer Ordnung Beispiel: 5n 2 + log 2 (n) = O(n 2 ) Teilaufgaben des Algorithmus mit kleinem Umfang 16

Bedeutung der O-Notation Die Definition der O-Notation besagt, dass wenn T(n) = O(g(n)), ab irgendeinem n 0 die Gleichung T(n) c. g(n) gilt. Weil T(n) und g(n) Zeitfunktionen sind, ihre Werte also immer positiv sind, gilt: T(n) c ab irgendeinem n 0 g(n) Beide Funktionen können besser verglichen werden, wenn man den Grenzwert berechnet. lim n T(n) g(n) Wenn der Grenzwert existiert, dann gilt: T(n) = O(g(n)) Wenn der Grenzwert gleich 0 ist, dann bedeutet dies, dass g(n) sogar schneller wächst als T(n). Dann wäre g(n) eine zu große Abschätzung der Laufzeit. 17

Bedeutung der O-Notation Beispiel: 100n 3 + 15n 2 + 15 = O(n 3 )? lim n 100n3 + 15n 2 + 15 = 100 n 3 dann gilt: 100n 3 + 15n 2 + 15 = O(n 3 ) Beispiel: 3n + 7 = O(n) = O(n 2 ) = O(n 3 ) Ziel unserer Analyse ist es, die kleinste obere Schranke zu finden, die bei der ungünstigsten Dateneingabe vorkommen kann. 18

Klassifikation von Algorithmen Komplexitätsklassen nach Wachstumsgeschwindigkeit konstant O(1) logarithmisch O(log 2 n) O(log e n) linear O(n) quadratisch O(n 2 ) kubisch O(n 3 ) exponentiell O(2 n ) O(10 n ) 19

O(1) Die meisten Anweisungen in einem Programm werden nur einmal oder eine konstante Anzahl von Malen wiederholt. Wenn alle Anweisungen des Programms diese Eigenschaft haben, spricht man von konstanter Laufzeit. Beste Zielzeit bei der Entwicklung von Algorithmen! 20

O-Notation Beispiel: für T(n) = n 2 + 2n gilt n 2 + 2n = O(n 2 ) denn mit c=3 und ab n 0 =1 gilt 2n + n 2 c n 2 2n + n 2 3 n 2 Die Funktion T(n) liegt in der Komplexitätsklasse O(n 2 ) oder 2n + n 2 2 n 2 + n 2 2n 2 n 2 1 n Die Größenordnung der Funktion T(n) ist O(n 2 ) 21

Die Funktion sum berechnet für ein gegebenes n>0 die Summe aller Zahlen von 1 bis n Rekursiv direkt Formel von Gauß sum :: Integer -> Integer sum 0 = 0 sum :: Integer -> Integer sum n = div (n*(n+1)) 2 sum n = n + sum (n-1) T(n) = c 1 n c 1 = Zeitkosten einer Reduktion + einer Addition T(n) = O(n) T(n) = c 1 + c 2 c 1 = Zeitkosten einer Reduktion c 2 = Arithmetische Operationen T(n) = O(1) 22

Analyse mit Hilfe der O-Notation Nehmen wir an, wir möchten das größte Element einer Liste berechnen. 1. Lösung maxi :: (Ord a) => [a] -> a maxi [x] = x maxi (x:xs) all (<=x) xs = x otherwise = maxi xs Im Schlimmsten Fall brauchen wir n Reduktionen in der all-funktion, mit n gleich die Länge der Liste xs. 23

maxi [x] = x maxi (x:xs) all (<=x) xs = x otherwise = maxi xs maxi [x 1, x 2,, x n 1, x n ] Anzahl der Reduktionen all ( x 1 ) [x 2,, x n 1, x n ] (n) all ( x 2 ) [x 3,, x n 1, x n ] (n-1) all ( x 3 ) [x 4,, x n 1, x n ] (n-2)... all ( x [x n 2 ) n 1, x n ] 3 all ( x [x n 1 ) n ] 2 maxi [x n ] x n 1 Summe aller Reduktionen: (n)*(n+1)/2 T (n) = c 1 2 n2 + 1 2 n mit c=zeitkosten einer Reduktion T (n) = O(n 2 ) 24

Beispiel: Die eigentliche Analyse Das größte Element einer Liste. 2. Lösung quick_maxi :: (Ord a) => [a] -> a quick_maxi [x] = x quick_maxi (a:b:xs) = help_maxi a (b:xs) where help_maxi a [] = a help_maxi a (b:xs) a>b = help_maxi a xs otherwise = help_maxi b xs 25

quick_maxi [x] = x quick_maxi (a:b:xs) = help_maxi a (b:xs) where help_maxi a [] = a help_maxi a (b:xs) a>b = help_maxi a xs otherwise = help_maxi b xs quick_maxi [x 1, x 2,, x n 1, x n ] help_maxi x 1 (x 2, :[x 3,, x n 1, x n ]) Anzahl der Reduktionen help_maxi x 2 (x 3, :[x 4,, x n 1, x n ]) 1 1 T (n) = c n + 1 T (n) = O(n) help_maxi x 2 (x 4, :[x 5,, x n 1, x n ]) 1...... help_maxi x i (x n, :[]) 1 help_maxi x j [x n ] 1 26

Insertion-Sort isort [] = [] isort (a:x) = ins a (isort x) where ins a [] = [a] ins a (b:y) a<= b = a:(b:y) otherwise = b: (ins a y) Eingabe: n Zahlen n 3 7 9 2 0 1 4 5 6 0 8 2 3 7 5 Berechnungsschritte: Vergleichsoperationen oder Reduktionen Komplexitätsanalyse: Im schlimmsten Fall T(n) = 1+2+3+...+(n-1) = (n-1)n 2 = 1 2 n2 + 1 2 n = O(n 2 ) 27

Komplexität eines Algorithmus O-Notation Ω Notation θ-notation Obere Komplexitätsgrenze (höchstens) Untere Komplexitätsgrenze (mindestens) Genaue Komplexität (genau) 28

Definitionen: Ω Notation Komplexität eines Algorithmus Die Funktion T(n) = Ω (g(n)), wenn es positive Konstanten c und n 0 gibt, so dass T(n) c g(n) für alle n n 0 θ-notation Die Funktion T(n) = θ (g(n)) genau dann, wenn T(n) = O(g(n)) und T(n) = Ω (g(n)) 29

Beispiel: factorial 0 = 1 factorial n = n*factorial (n-1) Berechnung: factorial 6 => 6 * factorial 5 => 6 * (5 * factorial 4) => 6 * (5 * (4 * factorial 3)) => 6 * (5 * (4 * (3 * factorial 2))) => 6 * (5 * (4 * (3 * (2 * factorial 1)))) => 6 * (5 * (4 * (3 * (2 * (1 * factorial 0))))) => 6 * (5 * (4 * (3 * (2 * (1 * 1))))) => 6 * (5 * (4 * (3 * (2 * 1)))) => 6 * (5 * (4 * (3 * 2))) => 6 * (5 * (4 * 6)) => 6 * (5 * 24) => 6 * 120 => 720 Der Ausdruck wächst bei jedem rekursiven Aufruf der Funktion. Die Multiplikationen finden dann am Ende statt. 30

Implementierung der Funktion Fakultät Rekursive Definition factorial :: Int -> Int factorial 0 = 1 factorial n = n*factorial (n-1) Rechenzeit: Speicherplatz: T(n) = O(n) M(n) = O(n) 31

Funktionale Programmierung Rekursionsarten Lineare Rekursion Rekursive Funktionen, die in jedem Zweig ihrer Definition maximal einen rekursiven Aufruf beinhalten, werden als linear rekursiv bezeichnet. Endrekursion (tail recursion) Linear rekursive Funktionen werden als endrekursive Funktionen klassifiziert, wenn der rekursive Aufruf in jedem Zweig der Definition die letzte Aktion zur Berechnung der Funktion ist. Prof. Dr. Margarita Esponda

Beispiel einer endrekursiven Definition der Fakultätsfunktion quickfactorial n = factorial_helper 1 n where factorial_helper a 0 = a factorial_helper a n = factorial_helper (a*n) (n-1) Ablauf einer Berechnung: quickfactorial 6 => factorial_helper 1 6 => factorial_helper 6 5 => factorial_helper 30 4 => factorial_helper 120 3 => factorial_helper 360 2 => factorial_helper 720 1 => factorial_helper 720 0 => 720 Keine Zwischenausdrücke müssen gespeichert werden. Endrekursive Funktionen können aus diesem Grund oft vom Übersetzer (Compiler) optimiert werden, indem diese in einfache Schleifen verwandelt werden. 33

Implementierung der Funktion Fakultät Endrekursive Definition factorial :: Int -> Int factorial n = facthelper (1, n) where facthelper (a,0) = a facthelper (a,n) = facthelper (a*n, n-1) Wenn Tail-Recursion-Optimierungen gemacht werden. Rechenzeit: Speicherplatz: T(n) = O(n) M(n) = O(1) 34

Merge-Algorithmus n 0 1 3 4 6 7 8 9 0 0 4 5 7 7 8 9 35

Merge-Algorithmus 2*n 0 0 0 1 3 4 4 5 6 7 7 7 8 8 9 9 Wir hatten ursprünglich zwei sortierte Mengen mit Länge n. Nach jedem Vergleich wird eine Zahl sortiert, d.h. im schlimmsten Fall haben wir 2*n Vergleiche. T(n) = 2n = O(n) 36

Merge-Sort-Algorithmus teile teile 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 teile 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 teile teile merge merge 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 3 7 0 4 8 9 1 6 5 7 0 7 0 4 8 9 0 3 4 7 1 6 8 9 0 5 7 7 0 4 8 9 merge 0 1 3 4 6 7 8 9 0 0 4 5 7 7 8 9 merge 0 0 0 1 3 4 4 5 6 7 7 7 8 8 9 9 37

Merge-Sort-Algorithmus teile 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 teile 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 n-1 teile 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 Teil- Operatonen teile teile merge merge 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 3 7 0 4 9 8 1 6 5 7 0 7 0 4 9 8 =n 3 7 0 4 8 9 1 6 5 7 0 7 0 4 8 9 0 3 4 7 1 6 8 9 0 5 7 7 0 4 8 9 =n =n lg n merge 0 1 3 4 6 7 8 9 0 0 4 5 7 7 8 9 =n merge 0 0 0 1 3 4 4 5 6 7 7 7 8 8 9 9 n Vergleiche =n n log(n) 38

Merge-Sort-Algorithmus Eine Teilung kostet c 1 Ein Vergleich kostet c 2 T (n) = c 1 (n 1) + c 2 n log(n) Teiloperationen Vergleiche T (n) = O(n log(n))...nicht im Haskell! 39

1. Lösung (Hilfsfunktion): Merge-Sort-Algorithmus merge (Ord a) => [a] -> [a] -> [a] merge [] ys = ys merge xs [] = xs merge (x:xs) (y:ys) = if x <= y then x: (merge xs (y:ys)) else y: (merge (x:xs) ys) 40

1. Lösung: Merge-Sort-Algorithmus mergesortstart :: (Ord a) => [a] -> [a] mergesortstart [ ] = mergesort 0 [ ] mergesortstart xs = mergesort (length xs) xs mergesort :: Integer -> [a] mergesort _ [] = [] mergesort _ [x] = [x] mergesort _ [x,y] = if x <= y then [x,y] else [y,x] mergesort len xs = merge (mergesort h leftlist) (mergesort (len-h) rightlist) where schlecht! h = len `div` 2 leftlist = take h xs rightlist = drop h xs 41

2. Lösung (Hilfsfunktionen) Merge-Sort-Algorithmus split :: [a] -> [[a]] split [] = [] split [x] = [[x]] split (x:xs) = [x]: (split xs) merge :: (Ord a) => [a] -> [a] -> [a] merge [] ys = ys merge xs [] = xs merge (x:xs) (y:ys) x <= y = x: (merge xs (y:ys)) otherwise = y: (merge (x:xs) ys) 42

Merge-Sort-Algorithmus 2. Lösung mergelists :: (Ord a) => [[a]] -> [[a]] mergelists [] = [] mergelists [x] = [x] mergelists (x:y:xs) = (merge x y): mergelists xs mergesort :: (Ord a) => [[a]] -> [[a]] mergesort [x] = [x] mergesort (x:y:xs) = mergesort (mergelists (x:y:xs)) startmergesort :: (Ord a) => [a] -> [a] startmergesort xs = sortedlist where [sortedlist] = mergesort (split xs) 43