Algorithmen und Programmierung



Ähnliche Dokumente
Algorithmen und Datenstrukturen

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

Counting - Sort [ [ ] [ [ ] 1. SS 2008 Datenstrukturen und Algorithmen Sortieren in linearer Zeit

Übung Algorithmen und Datenstrukturen

9. Rekursion. 1 falls n 1 n (n 1)!, andernfalls. Experiment: Die Türme von Hanoi. Links Mitte Rechts. Mathematische Rekursion

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

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

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

Abstrakter Datentyp (ADT): Besteht aus einer Menge von Objekten, sowie Operationen, die auf diesen Objekten wirken.

Lösungsvorschlag Serie 2 Rekursion

4 Effizienz und Komplexität 3.1 1

Datenstrukturen und Algorithmen

Algorithmen und Datenstrukturen

Übung zu Algorithmen und Datenstrukturen (für ET/IT)

Speicher und Adressraum

Wiederholung: Zusammenfassung Felder. Algorithmen und Datenstrukturen (für ET/IT) Definition Abstrakter Datentyp. Programm heute

12. Dynamische Datenstrukturen

Algorithmen und Datenstrukturen Laufzeitabschätzung

Grundlagen: Algorithmen und Datenstrukturen

Datenstrukturen & Algorithmen

Algorithmen und Programmierung

Fallstudie: Online-Statistik

Kapitel 4: Dynamische Datenstrukturen. Algorithmen und Datenstrukturen WS 2017/18. Pro f. Dr. Sán do r Fe k e te

Ü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:

Algorithmen und Datenstrukturen I Grundlagen

Präfix-Summe. Das Schweizer Offiziersmesser der Parallelen Algorithmen. Parallele Rechenmodelle Präfix-Summe Brents Lemma Anwendungen

ALP II Dynamische Datenmengen Datenabstraktion

Algorithmen als systematische Vorgehensweisen zur Lösung eines formal definierten Problems

Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 15 (Linearer Speicher, Listen, Bäume)

Algorithmen als systematische Vorgehensweisen zur Lösung eines formal definierten Problems

Einführung in die Informatik I

3. Übungsblatt zu Algorithmen I im SoSe 2017

3AA. Prozeduren und Rekursion Prof. Dr. Wolfgang P. Kowalk Universität Oldenburg WS 2005/2006

11. Elementare Datenstrukturen

Schnittstellen, Stack und Queue

16. Dynamische Datenstrukturen

15. Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Aufrufstapel, Bau eines Taschenrechners, BNF, Parsen

13. Dynamische Datenstrukturen

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

AlgoDat Fragen zu Vorlesung und Klausur

Einführung in die Objektorientierte Programmierung Vorlesung 18: Lineare Datenstrukturen. Sebastian Küpper

Vorlesung Datenstrukturen

Algorithmen I. Tutorium 1-3. Sitzung. Dennis Felsing

Algorithmen und Datenstrukturen I. Grundlagen. Prof. Dr. Oliver Braun. Fakultät für Informatik und Mathematik Hochschule München

Übung Algorithmen und Datenstrukturen

Abstrakte Datentypen und Datenstrukturen

2. Algorithmische Methoden 2.1 Rekursion. 18. April 2017

Kapitel 5: Dynamisches Programmieren Gliederung

Programmierung 1 - Repetitorium

Algorithmen und Datenstrukturen (für ET/IT)

Einführung in die Programmierung

Übung Algorithmen und Datenstrukturen

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

Einführung Elementare Datenstrukturen. Der Konstruktor muß den Listenkopf head erzeugen. Der Vorgänger und Nachfolger von head ist head selbst.

Datenstrukturen und Algorithmen

1.4 Die Ackermannfunktion

Informatik I Komplexität von Algorithmen

Übungsblatt 13. Abgabe / Besprechung in Absprache mit dem Tutor

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

SS10 Algorithmen und Datenstrukturen 2. Kapitel Fundamentale Datentypen und Datenstrukturen

11. Rekursion. 1, falls n 1. n (n 1)!, andernfalls. Mathematische Rekursion. Rekursion in Java: Genauso! Unendliche Rekursion. n!

7. Verkettete Strukturen: Listen

Schwerpunkte. Verkettete Listen. Verkettete Listen: 7. Verkettete Strukturen: Listen. Überblick und Grundprinzip. Vergleich: Arrays verkettete Listen

Algorithmen I - Tutorium 28 Nr. 3

12. Rekursion Grundlagen der Programmierung 1 (Java)

Algorithmen und Datenstrukturen (ESE) Entwurf, Analyse und Umsetzung von Algorithmen (IEMS) WS 2014 / Vorlesung 9, Donnerstag 18.

Grundlagen: Algorithmen und Datenstrukturen

12. Rekursion. 1, falls n 1. n (n 1)!, andernfalls. Lernziele. Mathematische Rekursion. Rekursion in Java: Genauso! n! =

Organisatorisches. Algorithmen und Datenstrukturen (für ET/IT) Programm heute. Definition Feld. Definition Feld

Einführung in die Informatik

Programmieren und Problemlösen

Grundlagen: Algorithmen und Datenstrukturen

Stack. Seniorenseminar Michael Pohlig

ALP II Dynamische Datenmengen Datenabstraktion (Teil 2)

Algorithmen und Programmierung III

Informatik 1 ( ) D-MAVT F2010. Schleifen, Felder. Yves Brise Übungsstunde 5

Algorithmen und Datenstrukturen (für ET/IT)

Algorithmen und Datenstrukturen

1. Teilklausur Gruppe A. Bitte in Druckschrift leserlich ausfüllen!

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

Probeklausur: Programmierung WS04/05

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

3.3 Laufzeit von Programmen

Grundlagen der Informatik

Beispiellösung zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 5

Übungsblatt 13. Abgabe / Besprechung in Absprache mit dem Tutor

Datenstrukturen und Algorithmen. 7. Suchen in linearen Feldern

Technische Universität München SoSe 2018 Fakultät für Informatik, I Mai 2018 Dr. Stefanie Demirci

Kapitel 10. Komplexität von Algorithmen und Sortieralgorithmen

Übung Algorithmen und Datenstrukturen

Programm heute. Algorithmen und Datenstrukturen (für ET/IT) Feld als sequentielle Liste. Definition Feld

Algorithmen & Programmierung. Rekursive Funktionen (1)

6. Algorithmen auf Zeichenketten

2. Effizienz von Algorithmen

Asymptotik und Laufzeitanalyse

Übung Algorithmen und Datenstrukturen

Transkript:

Algorithmen und Programmierung Daniel Waeber Semester 3

Inhaltsverzeichnis 1 Analyse von Algorithmen 5 1.1 Laufzeit von Algorithmen............................. 5 1.1.1 Experimentelle Analyse.......................... 5 1.1.2 Theoretische Analyse von Algorithmen.................. 5 1.1.3 Pseudo-Code................................ 5 1.1.4 Random Accesss Machsine........................ 6 1.1.5 Laufzeit eines Algorithmus........................ 7 1.1.6 Wachstum der Laufzeit.......................... 7 1.1.7 O-Notation................................. 7 1.1.8 O-Notation HOWTO........................... 8 1.1.9 MEGA-Beispiel.......................... 8 1.1.10 Rekursionsbäume.............................. 9 1.1.11 Rekursion in der Registermaschine.................... 13 1.2 Datenstrukturen.................................. 14 1.2.1 Datenstruktur Stack............................ 14 1.2.2 Indirekte Anwendung von Stapeln................... 15 1.2.3 Dynamisierung Array-basierter Datenstrukturen............ 17 3

Kapitel 1 Analyse von Algorithmen Definition: Ein Algorithmus ist eine Schritt-für-Schritt Anweisung, mit dem ein Problem in endlich vielen Schritten lösbar ist. Frage nach Korrektheit und Effizienz des Algorithmus. 1.1 Laufzeit von Algorithmen im Allgemeinen transformieren Algorithmen eine Eingabe in eine Ausgabe die Laufzeit eines Algorithmus hängt typischerweise von der Eingabe-Grö se ab die Bestimmung der mittleren Laufzeit eines Algorithmus ist mathematisch oft sehr anspruchsvoll (selbst experimentell schwierig) Analyse der Laufzeit im schlechtesten Fall ( worst case ) 1.1.1 Experimentelle Analyse Implementation des Algorithmus. Messung der Laufzeit des Programms auf Eingaben verschiedener Grö se und Struktur. 1.1.2 Theoretische Analyse von Algorithmen Statt einer konkreten Implementierung verwenden wir eine abstraktere Beschreibung. (Pseudo Code) Charakterisierung der Laufzeit als Funktion der Länge der Eingabe Dabei werden alle Eingaben der Länge n berücksichtigt 1.1.3 Pseudo-Code abstrakte Beschreibung eines Algorithmus strukturierter als prosaische Beschreibung weniger detailierter als Java Programm 5

Beispiel: Algorithm arraymax(a,n) Input: Feld A von n ganzen Zahlen Output: Ein groesstes Element in A currentmax <- A[0] for i=1 to n-1 do if A[i] > currentmax then currentmax <- A[i] return currentmax Psedo-Code im Detail: Kontrollflussanweisungen for...do while...do repeat...until if...then...else... Deklarationen Methodenaufrufe f(arg1, arg2,...) Rückgabe return Ausdrücke Zuweisung Gleichheitstest =... 1.1.4 Random Accesss Machsine Rechenkern arithmetische Ausdrücke +,,,/ Kontrollflussoperatoren bedingte/unbedingte Sprünge konstante Zeit pro Operation linear organisierter Speicher mit wahlfreiem Zugriff jede Zelle speichert beliebige Zahl auf Zellen kann über ihre Adresse in konstanter Zeit zugegriffen werden unendlich gro ser Speicher primitive Operationen des Pseudocodes können in konstant vielen RAM-Anweisungen realisiert werden.

1.1.5 Laufzeit eines Algorithmus Definition: A Algorithmus (implementiert auf einer RAM) I Eingabe fuer A T A (I) = Anzahl der elementaren RAM Op. die A auf I durchfuehrt, Laufzeit von A auf I T A (n) = max(t A (I)) (I Eingabe der Groesse n) worst case Laufzeit von A Beispiel: Algorithm double(x) Eingabe: x N Ausgabe: 2 x y 2 x return y LOAD 0,0 MULT 0,2 STORE 0,0 RET Algorithm double(x) y x y y + x return z Algorithm double(x) z x for i = 1 to x do z z + 1 return z Da jede Zeile in 5 RAM-Operationen übersetzt werden kann, kann die Laufzeit auch in Pseudocode berechnet werden 1.1.6 Wachstum der Laufzeit Eine vernünftige Änderung des Maschinenmodells verändert die Laufzeit von Algorithmen nur um einen konstanten Faktor. Asymptotische Laufzeit berücksichtigt keine konstanten Faktoren und keine Terme niederer Ordnung. Wir interessieren uns daher für das asymptotische Wachstum von T A (n). 1.1.7 O-Notation Definition: f(n) O(g(n)) def n 0 c 0 : f(n) c g(n) n n 0

Beispiel: 12n 4 = O(n) 12n 4 12 n n 2 = O(n) nein Definition: f = Ω(g) gdw. g = Ω(f) 1.1.8 O-Notation HOWTO 1. Falls f(n) = d i=0 a in i (a d 0) f(n) = O(n d ) 2. Wir sagen 2n = O(n) statt 2n = O(n 2 ) 3. Wir sagen O(n) statt O(3n 6) Beispiel: Gegeben eine Folge von n Zahlen X[0],, X[n 1]. Berechne die Folge A[0],,A[n 1], wobei A[i] = 1 i+1 (X[0] + + X[i]) Algorithm PrefixAverage(X,n) Eingabe: X[0],...,X[n-1] Ausgabe: A[0],...,A[n-1], mit A[i] = (X[0],...,X[i) A <- leeres Feld mit n Zellen n for i=0 to n-1 n sum <- 0 n for j=0 to i n*(n+1)/2 sum <- sum + X[j] n*(n+1)/2 A[i] = sum / (i+1) n return A 1 T pa (n) = O(n + n + n + n(n+1) 2 + n(n+1) 2 + n + 1) = O(n 2 ) Algorithm Pr3f1x4v3r4g3(X,n) Eingabe: X[0],...,X[n-1] Ausgabe: A[0],...,A[n-1], mit A[i] = (X[0],...,X[i) A <- Feld mit n Zellen 1 sum <- A[0] 1 for 1 to n-1 n-1 sum <- sum + X[i] n-1 A[i] = sum / (i+1) n-1 return A 1 T p4 (n) = O(1 + 1 + (n 1) + (n 1) + (n 1) + 1) = O(n) 1.1.9 MEGA-Beispiel Wie löse ich ein Problem, wenn ich wei s, wie ich ein einfacheres Problem löse?

Beispiel: n! = n i; n! = i=0 { n (n 1)! n > 0 1 n = 0 Algorithmus fact(n) Eingabe: n Ausgabe: n! if(n=0) then 1 return 1 1 else return n*fact(n-1) 1+T(n-1) Sei T fact die Laufzeit von fact. T fact (0) c T fact (n) c + T fac (n 1) T fact (n) c + T fact (n 1) (1.1) c + (c + T fact (n 2) (1.2) 3c + T fact (n 3) (1.3) kc + T fact (n k) (1.4) (Beweis mit vollständiger Induktion über k) T fact (n) cn + T fact (0) cn + c = O(n) 1.1.10 Rekursionsbäume Beispiel: Algorithm Summe(A,n) Eingabe: Feld A von n Elementen Ausgabe: Summe \"uber A if n=1 return A[0] else return A[n]+Summe(A,n-1)

Aufruf durch C.K. ;) Summe(A,5) Summe(A,4) Summe(A,3) Summe(A,2) Summe(A,1) Beispiel: Potenzieren p(x,n) = x n wobei x,n N { 1 n = 0 p(x,n) = x p(x,n 1) n 1 Es geht aber besser, da x 2n = (x n ) 2 bzw. x 2n+1 = x(x n ) 2 1 n = 0 p(x,n) = (x k ) 2 = p(x, n 2 ) n = 2k x(x k ) 2 = x p(x, n 1 2 ) n = 2k + 1 Algorithm Power(x,n) Eingabe: nat\"urliche Zahlen x,n Ausgabe: x^n if n=0 then return 1 else if n gerade then y <- Power(x,n/2) return y*y else y <- Power(x,(n-1)/2) return y*y*x lineare Rekursion O(log n)

Power(x,n) Power(x,n/2) Power(x,n/4)... Power(x,1) T(x,n) O(1) + T(x, n 2 ) falls n gerade T(x,n) O(1) + T(x, n 2 ) falls n ungrade Algorithm Power(x,n) Eingabe: nat\"urliche Zahlen x,n Ausgabe: x^n if n=0 then return 1 else if n gerade then return Power(x,n/2)*Power(x,n/2) else return Power(x,n/2)*Power(x,n/2)*x # Op auf Schicht log n: c n # Op auf Schicht log n 1: c n/2 # Op auf Schicht log n k: c n/2 k Insgesamt: log n k=0 c n 2 k = c log n k=0 1 2 k c n Beispiel: Verfahren zum Summieren der Einträge eines Feldes. Algorithm Sum(A,i,n) Eingabe: Feld A von Zahlen mit Index i und Anzahl n Ausgabe: A[i]+A[i+1]+.. +A[i+n] if n=1 return A[i] return Sum(i,n/2)+Sum(i+n/2,(n+1)/2) Allgemein: # Op c log n i=0 2i = O(n)

Beispiel: Fibonacci Zahlen: F 0 = 0;F 1 = 1;F i = F i 1 + F i 2 Algorithm Fib(i) Eingabe i Ausgabe F(i) if(i=0) then return 0 if(i=1) then return 1 return fib(i-1)+fib(i-2) Schlechte Idee! Sei T(k) die Anzahl der rekursiven Aufrufe von Fib(k) T(0) = 1 T(1) = 1 T(2) = 1 + T(O) + T(1) T(k) = 1 + T(k 1) + T(k 2) F k 1 Da F k 2F k 2 hat man ein exponentielles Wachstum. F[0]=0 F[1]=1 F[i]=undef f\"ur 1<i<n Algorithm Fib(i) Eingabe i Ausgabe F(i) if F[i]=undef then F[i] = Fib(i-1) + Fib(i-2) return F[i] Beispiel für dynamisches Programmieren geht auch direkt über lineare Rekursion Übung Noch ( besser: ) ( ) Fi Fi 1 F = i 2 = F i 1 F i 1 ( 1 1 1 0 ) ( Fi 1 F i 2 d.h. v i = ( M v ) i 1 = M k v i k 1 mit v 1 = ; v 0 i = M i 1 v 1 M i 1 kann mittels sukz. Quadrieren in O(log(i)) berechnet werden! )

1.1.11 Rekursion in der Registermaschine Algorithm main x<-5 subroutine1(x) Algorithm subroutine1(i) k<- i+1 subroutine2(k) Algorithm subroutine2(j)... merken, welche Unterroutine gerade ausgeführt wird main subroutine1 subroutine2 Die Liste der laufenden Unterroutinen wird auf einem Methodenstapel (nach dem LIFO Prinzip) verwaltet Beim Aufruf einer neuen Methode legen wir auf den Stapel eine Datensatz der angibt, wer der Aufrufer ist, welche Rücksprungadresse ist zu verwenden und was sind die Werte der lokalen Variablen. ermöglicht Rekursion!

1.2 Datenstrukturen 1.2.1 Datenstruktur Stack Verwaltung eine Menge von Objekten nach LIFO Prinzip (im Moment soll der Stack nur ganze Zahlen beinhalten) erforderliche Operationen einfügen (push) füge das Argument der push-operation zu Menge verwalteten der Objekte hinzu extrahieren (pop) entfernt und liefert das letzte Element (isempty?) liefert true, wenn Stack leer ist (top) liefert das oberste Element ohne es zu entfernen Vorschau auf die algebraische Spezifikation Pop(Push(S,x)) = (S;x) Implementierung von Stacks mittels Feldern (Arrays) Allozieren eines Felds F der Größe M eine Zeigervariable z zeigt auf den ersten freien Eintrag in F ein push(x) speichert x in F[z] und setzt z z + 1 Falls z = M melde Fehler Stapel voll ein pop liefert F[z 1] und setzt z z 1 Falls z < 0 melde Fehler Stapel leer geht gut, solange nicht das Maximum M erreicht wird class IntArrayStack { int F[]; int z; int M; IntArrayStack(int m){ M = m; z = 0; F = new int[m]; } int pop() throws EmptyStackException {

} }... if(z == 0) throw... return F[--z]; Analyse: Linearer (in der Anzahl der in der Struktur verwalteten Objekte (M)) Platzbedarf O(1) für push + pop evtl. Ω(M) Zeit bei Initialisierung Problem/Einschränkung: Maximalgröße des Stapels muss bei Initialisierung bekannt sein Implementierungspezifische Ausnahmen! Implementierung von Stacks mittels verketteten Listen einfach verkettete Liste einfügen und entfernen am Anfang der Liste effektiv möglich Einfügen/Löschen am Anfang der Liste in O(1) am besten am 2. Element einfügen und vertauschen, damit Referenzen nicht zerstört werden. Einfügen/Löschen am Ende der Liste in Θ(n) Implementierung des Stapels Element im Stapel werden in der entsprechenden Reihenfolge in der e.v. Liste gespeichert. Dabei wird das oberste Element im Stapel am Anfang der Liste gespeichert. Platzbedarf Θ(n) Laufzeit push/pop/top O(1) 1.2.2 Indirekte Anwendung von Stapeln als Hilfsstruktur in anderen Datenstrukturen beim Entwurf von Algorithmen

Beispiel: Gegeben ist Feld X[0],,X[n 1] Berechnen für 0 i n 1 S[i] S[i] = maximale Anzahl von aufeinanderfolgenden unmittelbaren Element vor X[i], sodass X[j] X[i] Algorithm Span1(X,n) Eingabe: Feld X mit n Zahlen Ausgabe: Feld S S <- Neuse Feld von n Zahlen mit 0 for i=0 to n-1 do for j=0 to i do if X[i-j] <= X[i] then S[i]+=1 else break return S Analyse Auf benötigt der Algorithmus Θ(n 2 ) Es geht auch besser Abarbeiten von X von links nach rechts Wir speichern in einem Stack die Indizes der sichtbaren Elemente Am Index i hole Elemente aus dem Stapel, bis X[j] > X[i] (pop) Setze S[i] = i j Lege i auf den Stack (push) Algorithm Span2(X,n) S <- Neues Feld von n Zahlen A <- neuer leerer Stapel for i=0 to n-1 do while(!isempty(a) && X[top(A)] <= X[i]) pop(a) if(isempty(a)) then S[i] = i+1

else S[i] = i-top(a) push(a,i) Da nur n-mal gepushed wird, können wir nur n-mal popen. lineare Laufzeit 1.2.3 Dynamisierung Array-basierter Datenstrukturen Ziel: Stapel mit Arrays implementieren, aber die Größe der Struktur soll beliebig sein. Idee: Wir haben zu jeden Zeitpunkt ein Feld, in dem die Elemente des Stapels abspeichert sind. Wenn der Platz in dem Feld nicht mehr ausreicht, um alle Elemente des Stapels aufzunehmen, dann legen wir ein neues Feld (doppelter Größe) an und kopieren das alte Feld an dessen Anfang. Diese Struktur hat im worst-case ein schlechtes Laufzeitverhalten, da es push-operationen gibt, mit Ω(n) Laufzeit. (n = # Elemente im Stapel) ABER: Jede Folge von n push/pop Operationen benötigt O(n) Zeit Eine pop-operation benötigt im worst-case O(1) Zeit. D.h. alle pop-operationen Zusammen in einer Folge von n push/pop Operationen benötigen O(n) viel Zeit. Wir betrachten Folge von n push-operationen. Kosten # push m Kosten/Op 1000 1000 1000 1000 1 2000 < 2/op 2000 1000... 2000 1 4000 < 2/op 2000 2000... 4000 1 8000 < 2/op 4000 4000............ 1500 8000 < 2/op Die 2 i -te push-operation benoetigt O(2 i ) Alle anderen push-operationen benoetigen O(1)

{ O(2 mit T i ) fallsk = 2 i k O(1) sonst Gesamtzeit fuer n push-operationen: O(2 log n +1 1) + O(n) = O(n) n k=0 log n +1 log n T k = ( T 2 i)+o(n) = O( 2 i )+O(n) = k=0 k=0