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

Ähnliche Dokumente
3. Suchen. Das Suchproblem. Suche in Array. Lineare Suche. 1 n. i = n Gegeben Menge von Datensätzen.

Das Suchproblem. Gegeben Menge von Datensätzen. Beispiele Telefonverzeichnis, Wörterbuch, Symboltabelle

Das Suchproblem 4. Suchen Das Auswahlproblem Suche in Array

Das Suchproblem 4. Suchen Das Auswahlproblem Suche in Array

Das Suchproblem. Gegeben Menge von Datensätzen. Beispiele Telefonverzeichnis, Wörterbuch, Symboltabelle

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

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

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

14. Sortieren II Heapsort. Heapsort. [Max-]Heap 7. Heapsort, Quicksort, Mergesort. Binärer Baum mit folgenden Eigenschaften

Heapsort, Quicksort, Mergesort. 8. Sortieren II

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

Heapsort, Quicksort, Mergesort. 8. Sortieren II

Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Rekursion vs. Iteration, Sortieren

Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Rekursion vs. Iteration, Sortieren

Mathematische Rekursion

Suchen und Sortieren Sortieren. Mergesort

Abschnitt: Algorithmendesign und Laufzeitanalyse

Datenstrukturen. Mariano Zelke. Sommersemester 2012

Kap. 3: Sortieren (3)

2. Algorithmische Methoden 2.1 Rekursion. 18. April 2017

Algorithmen und Datenstrukturen (Th. Ottmann und P. Widmayer) Folien: Suchverfahren Autor: Stefan Edelkamp / Sven Schuierer

Aufgabe 8. 1 Arbeitsweise illustrieren. 2 Korrektheitsbeweis führen. 3 Laufzeitanalyse durchführen.

Formaler. Gegeben: Elementfolge s = e 1,...,e n. s ist Permutation von s e 1 e n für eine lineare Ordnung ` '

Grundlagen: Algorithmen und Datenstrukturen

Übung Algorithmen und Datenstrukturen

Kapitel 2. Weitere Beispiele Effizienter Algorithmen

QuickSort ist ein Sortieralgorithmus, der auf der Idee des Teile & Beherrsche beruht, und das gegebene Array an Ort und Stelle (in place) sortiert

G. Zachmann Clausthal University, Germany

Algorithmen und Datenstrukturen Kapitel 2: Korrektheit von Algorithmen und Laufzeitanalyse rekursiver Algorithmen (mittels Rekurrenzgleichungen)

Mi, 21. Mai, ab 12:30 Uhr, in E23 (OH14) Dann ab 14:30 Uhr: Motivation: Gegeben: hier: später: Aufgabe:

Sortieren & Co. KIT Institut für Theoretische Informatik

Algorithmen I - Tutorium 28 Nr. 2

Algorithmen und Datenstrukturen Kapitel 2: Korrektheit von Algorithmen und Laufzeitanalyse rekursiver Algorithmen (mittels Rekurrenzgleichungen)

Sortieren II / HeapSort Heaps

Proseminar Effiziente Algorithmen

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

Algorithmen und Datenstrukturen

Übung Algorithmen und Datenstrukturen

Aufgabe (Schreibtischtest, lexikographische Ordnung)

Informatik II, SS 2018

Das Divide - and - Conquer Prinzip. Quicksort Formulierung und Analyse des Prinzips Geometrisches Divide and Conquer - Closest-Pair - Segmentschnitt

Übung Algorithmen und Datenstrukturen

Datenstrukturen und Algorithmen Beispiellösung zu Heimübungsblatt 7. Abbildung 1: Das Array A als Baum (vgl. Foliensatz 16, Folie 3)

Übung Algorithmen und Datenstrukturen

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

Inhalt Kapitel 2: Rekursion

6 Quicksort. die mittlere Laufzeit Θ(n log n) beträgt und. die in der asymptotischen Notation verborgenen Konstanten sehr klein sind.

Lösungsvorschlag Serie 2 Rekursion

Kapitel 6 Elementare Sortieralgorithmen

INSERTION-SORT: Ja, Es wird immer das erste, kleinste Element an die neue Liste angehängt.

Algorithmen und Datenstrukturen

1.3 Erinnerung: Mergesort

1. Musterlösung. Problem 1: Average-case-Laufzeit vs. Worst-case-Laufzeit ** i=1

Einführung in die Informatik 2

18. Natürliche Suchbäume

Übersicht. Datenstrukturen und Algorithmen. Divide-and-Conquer. Übersicht. Vorlesung 9: Quicksort (K7)

9. Natürliche Suchbäume

8 Anwendung: Suchen. Folge a ganzer Zahlen; Element x. Wo kommt x in a vor?

Algorithmen & Komplexität

6 Algorithmen und Datenstrukturen

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

Quicksort ist ein Divide-and-Conquer-Verfahren.

Algorithmen und Datenstrukturen

Ein sortiertes Feld kann in O(log n) durchsucht werden, z.b. mit Binärsuche. Der Algorithmus 1 gibt den Pseudocode der binären Suche an.

4 Rekursionen. 4.1 Erstes Beispiel

3.2. Divide-and-Conquer-Methoden

Rekursive Funktionen

15. Zeiger, Algorithmen, Iteratoren und Container II

Speicher und Adressraum

Algorithmentheorie Randomisierung

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

Algorithmen und Datenstrukturen

Algorithmen und Datenstrukturen

Auswählen nach Rang (Selektion)

Übung Informatik I - Programmierung - Blatt 3

Vorkurs Informatik WiSe 17/18

Fibonacci-Suche. Informatik I. Fibonacci-Suche. Fibonacci-Suche. Einführung. Rainer Schrader. 24. Mai 2005

Algorithmen & Komplexität

Java. public D find(k k) { Listnode K, D n = findnode(k); if(n == null) return null; return n.data; Java

Algorithmen und Datenstrukturen

8. A & D - Heapsort. Werden sehen, wie wir durch geschicktes Organsieren von Daten effiziente Algorithmen entwerfen können.

Datenstrukturen & Algorithmen

Folge 13 - Quicksort

Übersicht. Datenstrukturen und Algorithmen. Übersicht. Heaps. Vorlesung 8: Heapsort (K6) Joost-Pieter Katoen. 7. Mai 2015

12. Java Fehler und Ausnahmen

Programm heute. Algorithmen und Datenstrukturen (für ET/IT) Suchen. Lineare Suche. Such-Algorithmen. Sommersemester Dr.

Informatik II, SS 2014

2.2 Allgemeine (vergleichsbasierte) Sortierverfahren

Exponentielle Suche 4/26/10. Beweis für. Situation: Idee: suche zunächst "rechten Rand" r, so dass k < Ar Algo: Analyse:

21. Greedy Algorithmen. Aktivitätenauswahl, Fractional Knapsack Problem, Huffman Coding Cormen et al, Kap. 16.1, 16.3

Programmieren I. Kapitel 7. Sortieren und Suchen

Aufgabe (Schreibtischtest, Algorithmenanalyse)

Übung Algorithmen und Datenstrukturen

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

Algorithmen und Datenstrukturen (Th. Ottmann und P. Widmayer) Folien: Spezielle Sortierverfahren Autor: Sven Schuierer

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

Randomisierte Algorithmen 2. Erste Beispiele

Algorithmen und Datenstrukturen

Transkript:

Experiment: Die Türme von Hanoi. Rekursion Mathematische Rekursion, Terminierung, der Aufrufstapel, Beispiele, Rekursion vs. Iteration Links Mitte Rechts Mathematische Rekursion Viele mathematische Funktionen sind sehr natürlich rekursiv definierbar. Das heisst, die Funktion erscheint in ihrer eigenen Definition. n! =, falls n n (n )!, andernfalls Rekursion in Java: Genauso! n! = falls n n (n )!, andernfalls public static int fakultaet ( int n) if (n <= ) return ; else return n fakultaet (n ); n! fakultaet(n) n! fakultaet(n ) 0 0

Unendliche Rekursion Rekursive Funktionen: Terminierung ist so schlecht wie eine Endlosschleife...... nur noch schlimmer ( verbrennt Zeit und Speicher) Beispiel: f() f() f() f()... stack overflow public static void f () f (); Wie bei Schleifen brauchen wir Fortschritt Richtung Terminierung fakultaet(n) terminiert sofort für n, andernfalls wird die Funktion rekursiv mit Argument < n aufgerufen. n wird mit jedem Aufruf kleiner. 0 0 Rekursive Funktionen: Auswertung Der Aufrufstapel Beispiel: fakultaet() public static int fakultaet (int n) if (n <= ) return ; return n * fakultaet(n-); // n > Initialisierung des formalen Arguments: n = Rekursiver Aufruf mit Argument n, also Bei jedem Funktionsaufruf: Wert des Aufrufarguments kommt auf einen Stapel Es wird immer mit dem obersten Wert gearbeitet Am Ende des Aufrufs wird der oberste Wert wieder vom Stapel gelöscht n =! = fakultaet() n =! = fakultaet() n =! = fakultaet() n =! = fakultaet() System.out.println(fakultaet()) 0 0

Euklidischer Algorithmus findet den grössten gemeinsamen Teiler gcd(a, b) zweier natürlicher Zahlen a und b basiert auf folgender mathematischen Rekursion: gcd(a, b) = a, falls b = 0 gcd(b, a mod b), andernfalls Euklidischer Algorithmus in Java gcd(a, b) = public static int gcd(int a, intb) if (b == 0) return a; else return gcd(b, a%b); a, falls b = 0 gcd(b, a mod b), andernfalls Terminierung: a mod b < b, also wird b in jedem rekursiven Aufruf kleiner. 0 0 Fibonacci-Zahlen 0, falls n = 0 F n :=, falls n = F n + F n, falls n > Resultat: 0,,,,,,,,,,,... Fibonacci-Zahlen in Java Laufzeit fib(0) dauert ewig, denn es berechnet F -mal, F -mal, F -mal, F -mal, F -mal, F -mal... F ca. mal (!) public static int fib ( int n) if (n == 0 n == ) return n; else return fib (n ) + fib(n ); Korrektheit und Terminierung sind klar, aber...

Schnelle Fibonacci-Zahlen Schnelle Fibonacci-Zahlen in Java Idee: Berechne jede Fibonacci-Zahl nur einmal, in der Reihenfolge F 0, F, F,..., F n! Merke dir jeweils die zwei letzten berechneten Zahlen (Variablen a und b)! Berechne die nächste Zahl als Summe von a und b! public static int fib ( int n)\ if (n == 0) return 0; if (n <= ) return ; int a = ; int b = ; for (int i = ; i <= n; ++i) int a_old = a; a = b; b += a_old; return b; // F() // F() // F(i ) // F(i ) // F(i ) += F(i ) > F(i) Das Suchproblem Gegeben. Suchen Menge von Datensätzen. Beispiele Telefonverzeichnis, Wörterbuch, Symboltabelle Jeder Datensatz hat einen Schlüssel k. Schlüssel sind vergleichbar: eindeutige Antwort auf Frage k k für Schlüssel k, k. Aufgabe: finde Datensatz nach Schlüssel k.

Suche in Array Lineare Suche Gegeben Array A mit n Elementen (A[],..., A[n]). Schlüssel b Gesucht: Index k, k n mit A[k] = b oder nicht gefunden. Durchlaufen des Arrays von A[] bis A[n]. Bestenfalls Vergleich. Schlimmstenfalls n Vergleiche. Annahme: Jede Anordnung der n Schlüssel ist gleichwahrscheinlich. Erwartete Anzahl Vergleiche: 0 n n i= i = n +. Suche in sortierten Array Divide and Conquer! Gegeben Suche b =. Sortiertes Array A mit n Elementen (A[],..., A[n]) mit A[] A[] A[n]. Schlüssel b Gesucht: Index k, k n mit A[k] = b oder nicht gefunden. 0 0 0 b < b > 0 b > 0 0 0 b < erfolglos 0

Binärer Suchalgorithmus BSearch(A,b,l,r) Input : Sortiertes Array A von n Schlüsseln. Schlüssel b. Bereichsgrenzen l r n oder l > r beliebig. Output : Index des gefundenen Elements. 0, wenn erfolglos. m (l + r)/ if l > r then // erfolglose Suche return 0 else if b = A[m] then// gefunden return m else if b < A[m] then// Element liegt links return BSearch(A, b, l, m ) else // b > A[m]: Element liegt rechts return BSearch(A, b, m +, r) Analyse (Schlimmster Fall) Rekurrenz (n = k ) Teleskopieren: T (n) = d falls n =, T (n/) + c falls n >. ( n ) ( n ) T (n) = T + c = T + c ( n ) = T + i c ( i n = T + log n) n c. Annahme: T (n) = d + c log n Analyse (Schlimmster Fall) Resultat T (n) = d falls n =, T (n/) + c falls n >. Vermutung : T (n) = d + c log n Beweis durch Induktion: Induktionsanfang: T () = d. Hypothese: T (n/) = d + c log n/ Schritt (n/ n) Theorem Der Algorithmus zur binären sortierten Suche benötigt Θ(log n) Elementarschritte. T (n) = T (n/) + c = d + c (log n ) + c = d + c log n.

Iterativer binärer Suchalgorithmus Korrektheit Input : Sortiertes Array A von n Schlüsseln. Schlüssel b. Output : Index des gefundenen Elements. 0, wenn erfolglos. l ; r n while l r do m (l + r)/ if A[m] = b then return m else if A[m] < b then l m + else r m return 0; Algorithmus bricht nur ab, falls A leer oder b gefunden. Invariante: Falls b in A, dann im Bereich A[l,..., r] Beweis durch Induktion Induktionsanfang: b A[,.., n] (oder nicht) Hypothese: Invariante gilt nach i Schritten Schritt: b < A[m] b A[l,.., m ] b > A[m] b A[m +,.., r] Min und Max. Auswählen? Separates Finden von Minimum und Maximum in (A[],..., A[n]) benötigt insgesamt n Vergleiche. (Wie) geht es mit weniger als n Vergleichen für beide gemeinsam?! Es geht mit N Vergleichen: Vergleiche jeweils Elemente und deren kleineres mit Min und grösseres mit Max.

Das Auswahlproblem Ansätze Eingabe Unsortiertes Array A = (A,..., A n ) paarweise verschiedener Werte Zahl k n. Ausgabe: A[i] mit j : A[j] < A[i] = k Spezialfälle k = : Minimum: Algorithmus mit n Vergleichsoperationen trivial. k = n: Maximum: Algorithmus mit n Vergleichsoperationen trivial. k = n/ : Median. Wiederholt das Minimum entfernen / auslesen: O(k n). Median: O(n ) Sortieren (kommt bald): O(n log n) Pivotieren O(n)! 0 Pivotieren Algorithmus Partition(A[l..r], p) Wähle ein Element p als Pivotelement Teile A in zwei Teile auf, den Rang von p bestimmend. Rekursion auf dem relevanten Teil. Falls k = r, dann gefunden. p > > > p > > > > r n Input : Array A, welches den Sentinel p im Intervall [l, r] mindestens einmal enthält. Output : Array A partitioniert in [l..r] um p. Rückgabe der Position von p. while l < r do while A[l] < p do l l + while A[r] > p do r r swap(a[l], A[r]) if A[l] = A[r] then l l + return l-

Korrektheit: Invariante Korrektheit: Fortschritt Invariante I: A i p i [0, l), A i > p i (r, n], k [l, r] : A k = p. while l < r do while A[l] < p do l l + while A[r] > p do r r swap(a[l], A[r]) if A[l] = A[r] then l l + return l- I I und A[l] p I und A[r] p I und A[l] p A[r] I while l < r do while A[l] < p do l l + while A[r] > p do r r swap(a[l], A[r]) if A[l] = A[r] then l l + return l- Fortschritt wenn A[l] < p Fortschritt wenn A[r] > p Fortschritt wenn A[l] > p oder A[r] < p Fortschritt wenn A[l] = A[r] = p Wahl des Pivots Das Minimum ist ein schlechter Pivot: worst Case Θ(n ) p p p p p Ein guter Pivot hat linear viele Elemente auf beiden Seiten. p ɛ n ɛ n Analyse Unterteilung mit Faktor q (0 < q < ): zwei Gruppen mit q n und ( q) n Elementen (ohne Einschränkung q q). T (n) T (q n) + c n = c n + q c n + T (q n) =... = c n c n i=0 q i geom. Reihe = c n q = O(n) log q (n) i=0 q i + T ()

Wie bekommen wir das hin? Der Zufall hilft uns (Tony Hoare, ). Wähle in jedem Schritt einen zufälligen Pivot. schlecht gute Pivots schlecht Wahrscheinlichkeit für guten Pivot nach einem Versuch: =: ρ. Wahrscheinlichkeit für guten Pivot nach k Versuchen: ( ρ) k ρ. Erwartungswert der geometrischen Verteilung: /ρ = Algorithmus Quickselect (A[l..r], i) Input : Array A der Länge n. Indizes l i r n, so dass für alle x A[l..r] gilt, dass j A[j] x l und j A[j] x r. Output : Partitioniertes Array A, so dass j A[j] A[i] = i if l=r then return; repeat wähle zufälligen Pivot x A[l..r] p l for j = l to r do if A[j] x then p p + l+r until p (l+r) m Partition(A[l..r], x) if i < m then quickselect(a[l..m], i) else quickselect(a[m..r], i)