Einschub: Anweisungen und Bedingungen für PAP und Struktogramme (1) Anweisungen: Eingabeanweisungen, z.b. Eingabe: x Ausgabeanweisungen, z.b. Ausgabe: Das Maximum ist, max Die Symbole x und max werden hier für Variablen benutzt. Variablen nehmen Daten während der Abarbeitung des Programms auf. Eingabe: x Ausgabe: Das Maximum ist, max Peter Sobe 36 Einschub: Anweisungen und Bedingungen für PAP und Struktogramme (2) Anweisungen: Zuweisungen konstanter Werte, z.b. z = 5 Zuweisungen im Stil mathematischer Ausdrücke, z.b. y = z * 2. Hier wird der Variable y der Wert zugewiesen, der sich aus z*2 errechnet. Allgemein wird der links von = stehenden Variablen der Wert des Ausdrucks rechts zugewiesen. z = 5 y = z * 2 Nicht gültig: x+y = 10*z Das ist keine Zuweisung, obwohl es ein möglicher mathematischer Ausdruck ist. Peter Sobe 37
Einschub: Anweisungen und Bedingungen für PAP und Struktogramme (3) Bedingungen: Als Frage formuliert, ob eine Variable einen bestimmten Wert aufweist, z.b. z = 0?. Die Bedingung ist dann erfüllt, wenn z den Wert 0 besitzt. Das? kann (muss nicht) verwendet werden. Als Gleichung formuliert, z.b. y = z * z?. Wenn die linke und rechte Seite der Gleichung den gleichen Wert ergeben, dann ist die Bedingung erfüllt. Als Ungleichung formuliert, z.b. y > z?. Nur bei ungleicher linker und rechter Seite ist die Bedingung erfüllt. z = 5? ja nein Achtung: Ein Ausdruck wirkt unterschiedlich, je nach dem, ob er in einer Anweisung oder in einer Bedingung verwendet wird. Peter Sobe 38 Einschub: Anweisungen und Bedingungen für PAP und Struktogramme (4) Felder: Algorithmen arbeiten oft auf Feldern, die N einzelne Variable als Folge enthalten, z.b. z 0, z 1, z 2, z N-1 Die einzelnen Elemente können im PAP oder Struktogramm mit Index angegeben werden. Der Index kann ein konkreter Wert sein (z.b. z 0 ) oder auch als Variable angegeben werden (z.b. z i ). a 0 = 0 i = 5 a i = a i-1 * a i-1 z i = 0? ja nein Peter Sobe 39
Einschub: Anweisungen und Bedingungen für PAP und Struktogramme (5) Felder (Fortsetzung): Der Index kann auch mit Indexklammern geschrieben werden, z.b. z[0] oder z[i-1]. a[0] = 0 i = 5 a[i] = a[i-1]* a[i-1] z[i]= 0? ja nein Die Programmierung von Feldzugriffen in C erfolgt mit Indexklammern. Peter Sobe 40 Rekursive Algorithmen In der Mathematik sind viele Funktionen rekursiv definiert. Der Begriff der Rekursion beinhaltet, dass zur Definition einer Funktion diese selbst wieder mit benutzt wird, allerdings mit anderen Argumenten. Eine rekursive Definition benötigt stets eine (nichtrekursive) Anfangs- bzw. Abbruchbedingung. Beispiel: Fakultät rekursive Definition : fak(n) = n * fak(n-1) Anfangsbedingung: fak(0) = 1 Peter Sobe 41
Rekursive Algorithmen - Charakteristika Eine solche Definition ist in der Regel kurz und übersichtlich. Man erkennt sofort die Grundstruktur des Algorithmus. Eine solche rekursive Definition lässt sich auch sehr leicht unter Verwendung rekursiver Prozeduren ( Funktionen) implementieren. Allerdings ist der implementierte Algorithmus häufig ineffizient, d.h. mit einem hohen Ressourcenverbrauch (Speicher und Rechenzeit) verbunden. Bestimmte rekursive Algorithmen lassen sich in iterative Algorithmen umschreiben und damit effizienter implementieren. Dies trifft insbesondere auf eine sogenannte endständige Rekursion zu, wie z.b. bei der Fakultät. Peter Sobe 42 Rekursive Algorithmen - Fakultät Das folgende Struktogramm enthält die Umsetzung der rekursiven Definition: fak(n) Eingangsgröße: n Ausgangsgröße: Rückkehrwert if (n==0) return 1 then else return (n*fak(n-1)) Peter Sobe 43
Rekursive Algorithmen Fibonacci-Zahlen Rekursive Definition der Fibonacci-Zahlen: fibo(n) = fibo(n-1) + fibo(n-2) Anfangsbedingung: fibo(0)=0, fibo(1)=1 Das folgende Struktogramm enthält die Umsetzung der rekursiven Definition: fibo(n) Eingangsgröße: n Ausgangsgröße: Rückkehrwert if (n<2) then return n else return (fibo(n-1)+fibo( n-2)) Peter Sobe 44 Rekursive Algorithmen Turm von Hanoi Das Problem beim Turm von Hanoi besteht in der folgenden Aufgabe: 1. Gegeben ist ein Turm auf einem Standplatz A aus n Scheiben, die übereinander liegen, und zwar immer eine kleinere auf einer größeren Scheibe. 2. Der Turm soll auf einen zweiten Platz B umgesetzt werden, wobei aber beim Umsetzen immer nur eine kleinere auf eine größere Scheibe gelegt werden darf. 3. Bei der Umsetzung darf ein dritter Hilfsplatz C mitbenutzt werden. Das C-Programm für dieses Problem wird in der Vorlesung vorgeführt. Es dient als Experimentierprogramm für einen Turm mit einer wählbaren Scheibenanzahl zum Studium der Aufgabenstellung. Peter Sobe 45
Rekursive Algorithmen Turm von Hanoi Analysiert man das Problem beim Turm von Hanoi so erkennt man, dass man beim Umsetzen des Turms von n Scheiben vom Platz A zum Platz B erst einmal den Turm von n-1 Scheiben über der größten Scheibe von A nach dem Hilfsplatz C umsetzen muss, um einen Zug der größten Scheibe vom Platz A zum Platz B vornehmen zu können. Danach muss der Turm von n-1 Scheiben vom Platz C wieder auf den Platz B umgesetzt werden. Peter Sobe 46 Rekursive Algorithmen Turm von Hanoi Platz A Platz B Platz C Ausgangssituation Turm soll nach Platz B umgesetzt werden Peter Sobe 47
Rekursive Algorithmen Turm von Hanoi Platz A Platz B Platz C Turm mit n-1 Scheiben über der größten Scheibe muss auf Hilfsplatz C umgesetzt werden. Peter Sobe 48 Rekursive Algorithmen Turm von Hanoi Platz A Platz B Platz C Größte Scheibe kann jetzt durch einen Zug vom Platz A zum Platz B befördert werden. Peter Sobe 49
Rekursive Algorithmen Turm von Hanoi Platz A Platz B Platz C Turm mit n-1 Scheiben kann jetzt vom Hilfsplatz C zum Platz B umgesetzt werden. P. Sobe 50 Rekursive Algorithmen Turm von Hanoi Algorithmus rekursiv: Umsetz(n,A,B) = Umsetz(n-1,A,C), Zug (n,a,b), Umsetz(n-1,C,B) Die Rolle des Hilfsplatzes C wechselt von Ebene zu Ebene. Hilfsplatz ist immer der Platz, der in der Umsetzung nicht genannt ist. Bei Umsetz(...,A,C) ist es in der nächsten Ebene der Platz B usw.. Bezeichnet man den Platz A mit der Ziffer 0, den Platz B mit der Ziffer 1, und den Platz C mit der Ziffer 2, so kann der freie Platz immer mit 3-A-B bezeichnet werden. Peter Sobe 51
Rekursive Algorithmen Turm von Hanoi Struktogramm rekursiv: umsetz( n, a, b) if (n==0) return then k=3-a-b umsetz(n-1,a,k) zug(n,a,b) umsetz(n-1,k,b) else zug( n, a, b) Ausgabe: "snr=",n,"von ",p[a],"->",p[b] Peter Sobe 52 Rekursive Algorithmen Prinzip Teile und Herrsche Das Prinzip Teile und Herrsche (engl. divide and conquer bzw. lat. divide et impera) ist für die Verwendung rekursiver Algorithmen zugeschnitten. Man versucht den Grundbereich an Eingangsdaten für den Algorithmus in meist zwei Teile (die nicht unbedingt gleich groß sein müssen) aufzuteilen. Danach wird der eigentliche Algorithmus auf die erzeugten Teile nacheinander angewandt (Herrsche). Der Algorithmus teilt nun wieder die Teile in weitere Teile und bearbeitet diese weiter, was weitere rekursive Aufrufe zur Folge hat. Der rekursive Algorithmus, muss also die Teilung selbst mit enthalten. Peter Sobe 53
Rekursive Algorithmen Quicksort (1) Das Prinzip Teile und Herrsche wird für einen schnellen Sortieralgorithmus (Quicksort) angewandt. Die Aufteilung des Grundbereichs wird in einen linken und in einen rechten Teil durch eine Funktion(Prozedur) grupp vorgenommen. grupp(a[],l,r) while (l<r) if (a[l+1]<a[l]) then tausch(&a[l+1],&a[l]) l=l+1 else tausch(&a[l+1],&a[r]) r=r-1 return l; Peter Sobe 54 Rekursive Algorithmen Quicksort (2) Der Quicksort-Algorithmus benutzt nun diesen Teile-Algorithmus als wesentlichen Bestandteil und hat als Herrsche-Teil den rekursiven Aufruf von sich selbst. quicksort(a[],links,rechts) if (rechts>links) then pos=grupp(a,links,rechts) // Teile in links u. rechts quicksort(a,links,pos-1) // Herrsche links quicksort(a,pos+1,rechts) // Herrsche rechts else Peter Sobe 55
Rekursive Algorithmen Quicksort (3) Beispiel: Sortiere die Zahlenfolge 8,5,6,3,4,1, deren Elemente in a[0] bis a[5] gespeichert sind. Quicksort(a,0,5) pos=grupp(a,0,5) 8 5 6 3 4 1, l=0, r=5: Bedingung a[l+1]<a[l] zutreffend, tausche a[0], a[1], setze l=l+1=1 5 8 6 3 4 1, l=1, r=5: Bedingung a[l+1]<a[l] zutreffend, tausche a[1], a[2], setze l=l+1=2 5 6 8 3 4 1, l=2, r=5: Bedingung a[l+1]<a[l] zutreffend, tausche a[2], a[3], setze l=l+1=3 5 6 3 8 4 1, l=3, r=5: Bedingung a[l+1]<a[l] zutreffend, tausche a[3], a[4], setze l=l+1=4 5 6 3 4 8 1, l=4, r=5: Bedingung a[l+1]<a[l] zutreffend, tausche a[4], a[5], setze l=l+1=5 5 6 3 4 1 8, l=r=5: Bedingung l<r nicht mehr zutreffend, Zyklus beenden, pos = 5 Rekursiver Aufruf: Quicksort(a,0,4), Quicksort(a,6,5) Peter Sobe 56 Rekursive Algorithmen Quicksort (4) Fortsetzung: Quicksort(a,0,4) pos=grupp(a,0,4) 5 6 3 4 1 8, l=0, r=4: Bedingung a[l+1]<a[l] nicht zutreffend, tausche a[1], a[4], setze r=r-1=3 5 1 3 4 6 8, l=0, r=3: Bedingung a[l+1]<a[l] zutreffend, tausche a[0], a[1], setze l=l+1=1 1 5 3 4 6 8, l=1, r=3: Bedingung a[l+1]<a[l] zutreffend, tausche a[1], a[2], setze l=l+1=2 1 3 5 4 6 8, l=2, r=3: Bedingung a[l+1]<a[l] zutreffend, tausche a[2], a[3], setze l=l+1=3 1 3 4 5 6 8, l=r=3: Bedingung l<r nicht mehr zutreffend, Zyklus beenden, pos = 3 Rekursiver Aufruf: Quicksort(a,0,2), Quicksort(a,4,4) Peter Sobe 57
Rekursive Algorithmen Quicksort (5) Fortsetzung: Quicksort(a,0,2) pos=grupp(a,0,2) 1 3 4 5 6 8, l=0, r=2: Bedingung a[l+1]<a[l] nicht zutreffend, tausche a[1], a[2], setze r=r-1=1 1 4 3 5 6 8, l=0, r=1: Bedingung a[l+1]<a[l] zutreffend, tausche a[1], a[1], setze l=l+1 1 4 3 5 6 8, l=r=1: Bedingung l<r nicht mehr zutreffend, Zyklus beenden, pos = 0 Rekursiver Aufruf: Quicksort(a,0,-1), Quicksort(a,1,2) Quicksort(a,1,2) pos=grupp(a,1,2) 1 4 3 5 6 8, l=1, r=2: Bedingung a[l+1]<a[l] zutreffend, tausche a[1], a[2], setze l=l+1=2 1 3 4 5 6 8, l=r=2: Bedingung l<r nicht mehr zutreffend, Zyklus beenden, pos = 2 Rekursiver Aufruf: Quicksort(a,1,1), Quicksort(a,3,2) Ende Peter Sobe 58