Programmieren in C. Rekursive Funktionen. Prof. Dr. Nikolaus Wulff



Ähnliche Dokumente
Programmierkurs Java

Praktikum zu Einführung in die Informatik für LogWiIngs und WiMas Wintersemester 2015/16. Vorbereitende Aufgaben

Würfelt man dabei je genau 10 - mal eine 1, 2, 3, 4, 5 und 6, so beträgt die Anzahl. der verschiedenen Reihenfolgen, in denen man dies tun kann, 60!.

1 topologisches Sortieren

Einführung in die Programmierung

Objektorientierte Programmierung

Programmieren in C. Felder, Schleifen und Fließkommaarithmetik. Prof. Dr. Nikolaus Wulff

Kontrollstrukturen und Funktionen in C

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Grundlagen der höheren Mathematik Einige Hinweise zum Lösen von Gleichungen

Programmieren in C. Macros, Funktionen und modulare Programmstruktur. Prof. Dr. Nikolaus Wulff

5 DATEN Variablen. Variablen können beliebige Werte zugewiesen und im Gegensatz zu

1 Vom Problem zum Programm

Primzahlen und RSA-Verschlüsselung

Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Mathematischer Vorbereitungskurs für Ökonomen

50. Mathematik-Olympiade 2. Stufe (Regionalrunde) Klasse Lösung 10 Punkte

Grundlagen der Theoretischen Informatik, SoSe 2008

7 Rechnen mit Polynomen

Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung)

Bitte wenden. Name: KURSARBEIT NR. 4 (10 DIFF GA) Seite 1

Alle Schlüssel-Karten (blaue Rückseite) werden den Schlüssel-Farben nach sortiert und in vier getrennte Stapel mit der Bildseite nach oben gelegt.

Informationsblatt Induktionsbeweis

C++ Tutorial: Timer 1

Algorithmen & Datenstrukturen 1. Klausur

Funktionale Programmierung mit Haskell

Professionelle Seminare im Bereich MS-Office

Übung Theoretische Grundlagen

Beweisbar sichere Verschlüsselung

C-Probeklausur (Informatik 1; Umfang: C, Teil 1; SS07)

Zeichen bei Zahlen entschlüsseln

Sortieralgorithmen. Inhalt: InsertionSort BubbleSort QuickSort. Marco Block

Informatik Grundlagen, WS04, Seminar 13

Gleichungen Lösen. Ein graphischer Blick auf Gleichungen

Beispiel(unten ist der Spielfeldrand):

Klausur WS 2006/07 Programmiersprache Java Objektorientierte Programmierung II 15. März 2007

Zahlenwinkel: Forscherkarte 1. alleine. Zahlenwinkel: Forschertipp 1

Überblick. Lineares Suchen

Datenexport aus JS - Software

Institut für Programmierung und Reaktive Systeme 25. August Programmier-Labor Übungsblatt. int binarysearch(int[] a, int x),

Wir machen neue Politik für Baden-Württemberg

15.3 Bedingte Wahrscheinlichkeit und Unabhängigkeit

Die Java Stream API. Funktionale Programmierung mit der Stream API des JDK 1.8. Prof. Dr. Nikolaus Wulff

Erwin Grüner

Wie lässt sich die Multiplikation von Bruchzahlen im Operatorenmodell und wie im Größenmodell einführen?

Wie halte ich Ordnung auf meiner Festplatte?

SOI Die Schweizer Informatikolympiade

Quadratische Gleichungen

Vorbereitung auf die SEPA-Umstellung

Java Kurs für Anfänger Einheit 5 Methoden

SMS/ MMS Multimedia Center

Bedienungsanleitung: Onlineverifizierung von qualifiziert signierten PDF-Dateien

Einführung in die Programmierung

Zählen von Objekten einer bestimmten Klasse

Beispiel Zusammengesetzte Zufallsvariablen

Projektzeit erfassen. Allgemeines. Projektzeit erfassen - Maske. Erklärung der Tabellenspalten. In Arbeit!

Anleitung über den Umgang mit Schildern

Einführung in die Programmierung

1. Man schreibe die folgenden Aussagen jeweils in einen normalen Satz um. Zum Beispiel kann man die Aussage:

Programmierung in C. Grundlagen. Stefan Kallerhoff

Lineare Gleichungssysteme

Widerrufsbelehrung der Free-Linked GmbH. Stand: Juni 2014

Webalizer HOWTO. Stand:

Einfache Arrays. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

Große Übung Praktische Informatik 1

Abiturprüfung Mathematik 2008 (Baden-Württemberg) Berufliche Gymnasien ohne TG Analysis, Aufgabe 1

Betragsgleichungen und die Methode der Fallunterscheidungen

Matrix42. Use Case - Sicherung und Rücksicherung persönlicher Einstellungen über Personal Backup. Version September

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

* Leichte Sprache * Leichte Sprache * Leichte Sprache *

Die reellen Lösungen der kubischen Gleichung

4. Dynamische Optimierung

4 Aufzählungen und Listen erstellen

Sichere Anleitung Zertifikate / Schlüssel für Kunden der Sparkasse Germersheim-Kandel. Sichere . der

Lösung. Prüfungsteil 1: Aufgabe 1

Breiten- und Tiefensuche in Graphen

Dokumentation: ZIBXL - Auswertung der internen Umbuchungen

Sortierverfahren. Sortierverfahren für eindimensionale Arrays

Übungen Programmieren 1 Felix Rohrer. Übungen

Widerrufsbelehrung. Sie haben das Recht, binnen vierzehn Tagen ohne Angabe von Gründen diesen Vertrag zu widerrufen.

In vergleichsbasierten Suchbäumen wird nicht in Schlüssel hineingeschaut.

Softwarelösungen: Versuch 4

Algorithmische Mathematik

Welche Lagen können zwei Geraden (im Raum) zueinander haben? Welche Lagen kann eine Gerade bezüglich einer Ebene im Raum einnehmen?

Was meinen die Leute eigentlich mit: Grexit?

Lineare Funktionen. 1 Proportionale Funktionen Definition Eigenschaften Steigungsdreieck 3

Der Zwei-Quadrate-Satz von Fermat

Algorithmen II Vorlesung am

AutoCAD Dienstprogramm zur Lizenzübertragung

Kapitalerhöhung - Verbuchung

Tangentengleichung. Wie lautet die Geradengleichung für die Tangente, y T =? Antwort:

Erfahrungen mit Hartz IV- Empfängern

Scala kann auch faul sein

ANLEITUNG - WIE UNTERSTÜTZE ICH AUF STARTNEXT?

Grundlagen der Programmierung Prof. H. Mössenböck. 14. Schrittweise Verfeinerung

Personen. Anlegen einer neuen Person

Die Post hat eine Umfrage gemacht

Viele Bilder auf der FA-Homepage

Analysis I für Studierende der Ingenieurwissenschaften

Transkript:

Programmieren in C Rekursive Funktionen Prof. Dr. Nikolaus Wulff

Rekursive Funktionen Jede C Funktion besitzt ihren eigenen lokalen Satz an Variablen. Dies bietet ganze neue Möglichkeiten Funktionen zu implementieren, die bis lang noch nicht betrachtet wurden. Ein Funktion kann sich selbst rekursiv aufrufen! Dies ist ein mächtiges Konzept der Sprache C, das nicht in jeder Programmiersprache möglich ist. Fortran oder Cobol kennen dies nicht... Prof. Dr. Nikolaus Wulff Programmieren in C 2

Verkettung von Funktionen Rekursion möglicht eine ganz neue Klasse von Algorithmen, diese gehen über die bis lang betrachteten einfachen Schleifen hinaus. Aus der Mathematik ist uns ein der Rekursion ähnliches Verfahren, die Verkettung zweier Funktionen f und g zu einer Funktion h, bekannt: h(x) := (f g)(x) = f(g(x)) Der Spezialfall f g ergibt genau die Konstellation, dass sich die Funktion f selber aufruft. Allerdings ist dies keine Rekursion! Prof. Dr. Nikolaus Wulff Programmieren in C 3

Verkettung versus Rekursion Eine Gleichung der Form f(x) = h(x, f (g(x))) führt zu einer Rekursion. Meist verknüpft mit einer weiteren Funktion g, die das Argument x modifiziert und einer Funktion h. Rekursion liegt vor, wenn die Funktion f sowohl auf der linken als auch der rechten Seite vorkommt! Eine solche Funktion f kann sich unter Umständen beliebig oft aufrufen. Meist mit modifizierten Argument x g(x) Damit ein solcher Algorithmus terminiert muss der Rekursion eine geeignete Grenze gesetzt werden. Prof. Dr. Nikolaus Wulff Programmieren in C 4

Rekursive Algorithmen Wir wollen einen Algorithmus sum entwickeln, der alle Zahlen von 1 bis n aufsummiert: n n = j=1 j Die Definition σ(n) für den Algorithmus sum legt eher einen Algorithmus nahe, der eine Schleife verwendet. Es kostet einige Überlegungen hierfür einen rekursiven Algorithmus zu finden... Prof. Dr. Nikolaus Wulff Programmieren in C 5

sum als Schleife Die folgende Implementierung von sum entspricht unserem bisherigen Programmierstil, wir verwenden eine Schleife: int sum(unsigned int n){ int j, s = 0; for(j=1; j<=n; j++) { s += j; return s; Es ist offensichtlich, dass diese Implementierung eine direkte Umsetzung der Definition der Formel σ(n) der letzten Folie ist. Prof. Dr. Nikolaus Wulff Programmieren in C 6

Aus Schleife wird Rekursion... Ein rekursiver Algorithmus lässt sich aus der Analyse der definierenden Formel gewinnen: n n = j=1 j n = n n 1 2 1 n 1 n = n j=1 j n = n n 1 Prof. Dr. Nikolaus Wulff Programmieren in C 7

sum per Rekursion Die folgende Implementierung berechnet die Summe per Rekursion: int sum(unsigned int n) { if(n>1) { return n + sum(n-1); return n; Um den Algorithmus besser zu verstehen, macht es Sinn ihn mit etwas Debug Output zu versehen... Verankerung sum(0) = 0 sowie sum(1) = 1 sum(n) = n + sum(n-1) Prof. Dr. Nikolaus Wulff Programmieren in C 8

sum per Rekursion static int depth = 0; int sum(unsigned int x) { depth++; printf("beg %d x: %d \n", depth, x); int y = x; if(x>1) { y += sum(x-1); printf("end %d sum(%d)=%d \n", depth, x, y); depth--; return y; Die Rekursionstiefe wird mit der statischen Variablen depth gezählt. Jeweils beim Eintritt und vor dem Verlassen der Methode werden depth, x und y ausgegeben. Prof. Dr. Nikolaus Wulff Programmieren in C 9

Rekursive Sum in Aktion Die folgende main Routine int main() { int y, x = 5; y = sum(x); printf("\nresult: sum(%d)=%d\n", x, y); return 0; BEG 1 x: 5 BEG 2 x: 4 BEG 3 x: 3 BEG 4 x: 2 BEG 5 x: 1 END 5 sum(1)=1 END 4 sum(2)=3 END 3 sum(3)=6 END 2 sum(4)=10 END 1 sum(5)=15 liefert als Ausgabe: Result: sum(5)=15 Prof. Dr. Nikolaus Wulff Programmieren in C 10

Call Graph von sum Aufruf mit Argument 5 liefert nach 5 Rekursionen das Ergebnis 15 depth =1 sum(5) return 5 + 10 = 15 depth =2 sum(4) return 4 + 6 = 10 depth =3 sum(3) return 3 + 3 = 6 depth =4 sum(2) return 2 + 1 = 3 depth =5 sum(1) return 1 sum(1) = 1 sum(x) x + sum(x-1) für x > 1 Prof. Dr. Nikolaus Wulff Programmieren in C 11

Die Fakultät Die Fakultät Funktion n! besitzt sowohl eine Definition per Produkt: n! := n j=1 j als auch eine rekursive Definition: 1! := 1 n! := n*(n-1)! Prof. Dr. Nikolaus Wulff Programmieren in C 12

Fakultät rekursiv long factorial(long n) { if (n>1) { return n*factorial(n-1); return 1; Die rekursive faktorial Implementierung der Fakultät ist ähnlich zur sum Funktion strukturiert. Wichtig bei rekursiven Funktionen ist es, eine geeignete Abbruchbedingung vorzusehen, ansonsten terminiert der Algorithmus nie. => Stackoverflow Dies ist vollkommen analog zur Problematik bei falsch programmierten Schleifen... Prof. Dr. Nikolaus Wulff Programmieren in C 13

Gemeinsamkeiten Die beiden Beispiele besitzen die Struktur: Mit der Funktion g(n)=n-1 und den Funktionen h 1 (n,m) = n+m für die Summe und h 2 (n,m)=n*m für die Fakultät. f n =h n, f g n n =h 1 n, g n =n g n =n n 1 n!=h 2 n, g n! =n g n!=n n 1! Die Funktion g garantiert durch Verkleinerung von n, dass die Abbruchbedingung erreicht wird. Prof. Dr. Nikolaus Wulff Programmieren in C 14

Binärdarstellung Ein Ganzzahl x soll binär dargestellt werden: n x= j=0 b j 2 j Die Entwicklungskoeffizienten b j {0,1 lassen sich mit dem Pseudo-Algorithmus while(x) { b = x mod 2 x = x/2 print(b) ermitteln, allerdings in der falschen Reihenfolge! Prof. Dr. Nikolaus Wulff Programmieren in C 15

Rekursive Binärdarstellung Ein rekursiver Algorithmus ermöglicht eine einfache Implementierung ohne revers Operation... void printbinaery(unsigned int x) { if (x<2) { printf( %d,x); else { printbinaery(x/2); printf( %d,x%2); Prof. Dr. Nikolaus Wulff Programmieren in C 16

Rekursive Sortierung Quicksort ist ein rekursiver Algorithmus. Aus einem unsortierten Feld wird ein Element p ausgewählt und der Rest in zwei Untermengen aufgeteilt. Eine Menge mit Elementen größer als das ausgewählte Element p, die andere mit Elementen kleiner gleich dem ausgewählten Element. Diese Unterteilung wird so lange vorgenommen bis die Teilmengen weniger als zwei Elemente haben, dann terminiert die jeweilige Rekursion. Am Ende aller Rekursionen ist das Feld sortiert. Prof. Dr. Nikolaus Wulff Programmieren in C 17

Rekursiver Quicksort void qindex(int v[], int left, int right); void qsort(int v[], int left, int right) { if (left>=right) return;/* Terminator */ int p = qindex(v, left, right); qsort(v, left, p-1); qsort(v, p+1, right); void sort(int v[], int length) { qsort(v, 0, length); sort initialisiert den rekursiven qsort Algorithmus. Dieser verwendet die Hilfsfunktion qindex, um rekursiv das Feld in zwei Teilbereiche zu unterteilen und zu sortieren. Prof. Dr. Nikolaus Wulff Programmieren in C 18

Pivot Element ermitteln void qswap(int a[], int x, int y) { int tmp=a[x]; a[x]=a[y]; a[y]=tmp; int qindex(int v[], int left, int right) { int i, p, mid = (left+right)/2; qswap(v, left, mid); /* store pivot element */ p = left; for(i=left+1; i<=right; i++) { if (v[i] < v[left]) { /* compare to pivot */ qswap(v, ++p, i); qswap(v, left, p); /* restore pivot element */ return p; /* v[left,...,p]<= v[p] */ Prof. Dr. Nikolaus Wulff Programmieren in C 19

Der Einfluss von qswap Was die Übersich bei der Rekursionsfolge erschwert, ist dass qindex mehrmals qswap aufruft. {5,3,9,1,6,7,0,2,8,4 Ausgangssituation {6,3,9,1,5,7,0,2,8,4 Pivotelement 6 sichern {6,3,9,1,5,7,0,2,8,4 3 3 {6,3,1,9,5,7,0,2,8,4 9 1 {6,3,1,5,9,7,0,2,8,4 9 5 {6,3,1,5,0,7,9,2,8,4 9 0 {6,3,1,5,0,2,9,7,8,4 7 2 {6,3,1,5,0,2,4,7,8,9 9 4 {4,3,1,5,0,2,6,7,8,9 Pivotelement 6 restaurieren Nach dem Aufruf von qindex liegt also die Folge {431502< 6 <{789 vor. Prof. Dr. Nikolaus Wulff Programmieren in C 20

Rekursion kann kompliziert sein... Die Rekursion dieses Algorithmus ist nicht mehr so einfach nachzuvollziehen: Vorbelegung int v[]={5,3,9,1,6,7,0,2,8,4; Es resultiert die folgende Folge von Rekursionen: {5,3,9,1,6,7,0,2,8,4 {4,3,1,5,0,2 {7,8,9 {0 {4,5,3,2 {7 {9 {2 {2,4,3 {3,2 Prof. Dr. Nikolaus Wulff Programmieren in C 21