Folienhandout - Professur Betriebssysteme

Werbung
Algorithmen und Programmierung – Iterationen
4.1 Einführung
Algorithmen und Programmierung
Wintersemester 2016/2017
4.1 Einführung
Motivierendes Beispiel
„Aufgabe“
Esse alle Pralinen in einer Pralinenschachtel!
Algorithmen und Programmierung
Annahme: Ich weiß, wie ich eine Praline essen kann.
4. Kapitel
Iterationen
Prof. Matthias Werner
Professur Betriebssysteme
Bildquelle: BeautifulCataya, CC 2.0
WS 2016/17 · M. Werner
Algorithmen und Programmierung – Iterationen
4.1 Einführung
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.1 Einführung
Variante 1
Variante 2
Esse die erste Praline von links in der ersten Reihe.
Esse die zweite Praline von links in der ersten Reihe.
..
.
Esse die Praline ganz rechts in der ersten Reihe.
Esse die erste Praline von links in der zweiten Reihe.
..
.
Esse die erste Praline von links in der letzten Reihe.
Esse die zweite Praline von links in der letzten Reihe.
..
.
I
Esse die Praline ganz rechts in der letzten Reihe.
I
2 / 31
I
Weise den Pralinen die Nummern 1 bis n zu
I
Zähle von 1 bis n und esse die Praline mit der jeweiligen Nummer
Anmerkung: Es findet eine Abbildung von der Menge der natürlichen Zahlen N auf
die Menge der Pralinen statt
Problem: Algorithmus1 ist evtl. sehr lang
1 Genau genommen ist es in der dargestellten Form gar kein Algorithmus; vgl. Kapitel 1.
WS 2016/17 · M. Werner
3 / 31
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
4 / 31
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.1 Einführung
Algorithmen und Programmierung – Iterationen
4.1 Einführung
Variante 3
Variante 4
I
Zähle die Pralinen á n
I
Zähle von 1 bis n und esse bei jeder Zahl jeweils eine Praline
I
I
I
Anmerkung: Der Vorgang des Essens wird für eine vorher bestimme Zahl von
Wiederholungen durchgeführt
WS 2016/17 · M. Werner
5 / 31
osg.informatik.tu-chemnitz.de
Anmerkung: Der Vorgang des Essens wird für eine (zunächst) unbestimme Zahl
von Wiederholungen durchgeführt
WS 2016/17 · M. Werner
Algorithmen und Programmierung – Iterationen
4.1 Einführung
6 / 31
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Unterschiedliche Sichtweisen
I
Solange noch eine Praline da ist: Esse eine (beliebige) Praline
4.2 Schleifen in C und Python
Wiederholen...
I ...für eine bestimmte Anzahl von Wiederholungen
I ...für Elemente einer Menge
I ...solange eine Bedingung (nicht) erfüllt ist
I
In C gibt es drei Arten von Schleifen:
I while-Schleife
I do-while-Schleife
I for-Schleife
I
I
Alle Varianten sind aufeinander abbildbar
I
Solche Wiederholungen heißen in Programmiersprachen Schleifen
I
Alle Schleifen nutzen Bedingungen
Jede davon kann2 die anderen simulieren
I
Schleifen gibt es in vielen (nicht allen!) Programmiersprachen
I
Welche genutzt wird, ist also z.T. Geschmackssache
I
Allgemein gibt es bei Schleifen immer etwas Invariantes/Konstantes und i.d.R.
etwas sich Änderndes
2 ...ggf unter Nutzung anderer Sprachkonstrukte...
WS 2016/17 · M. Werner
7 / 31
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
8 / 31
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
while-Schleife (Forts.)
while-Schleife
I
Die while-Schleife führt ein Statement solange aus, wie eine Bedingung wahr ist.
I
Sie arbeitet wie folgt:
1. Es wird überprüft, ob der Ausdruck in der Klammer nach dem Schlüsselwort
while eingehalten wird
Beispiele:
/ * sqr . c -- Heron ’s method * /
# include < stdlib .h >
# include < math .h >
# include < stdio .h >
2. Falls ja, wird eine Anweisung nach diesem Ausdruck ausgeführt
(á Schleifenkörper) und anschließen wieder zu 1. gesprungen
I Wenn die Schleife mehrere Anweisungen umfassen soll, müssen diese
in einem Block geklammert werden
# include < stdio .h >
int main ()
{
int i =3;
while (i >0) {
printf (" Cthulhu !\ n" );
i=i -1;
}
return 0;
}
int main ( int argc , char ** args )
{
double x =1.0;
double y= atof ( args [1]);
3. Falls nein, wird mit der ersten Anweisung nach dem Schleifenkörper
fortgesetzt
Anweisung (Schleifenkörper)
while ( fabs (y -x * x ) >0.00001){
x =0.5 * ( x+y/x );
}
printf ( " sqrt (% f) = %f .\ n" ,y ,x );
return 0;
}
while(i<10) i=i+1;
Bedingung
WS 2016/17 · M. Werner
9 / 31
WS 2016/17 · M. Werner
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
do-while-Schleife
Schleifen können zur Bearbeitung oder Belegung der Elemente eines Array zur Laufzeit
genutzt werden
# include < stdio .h >
enum { arraysize =12};
/ * constant for array size * /
I
Die do-while-Schleife ähnelt der while-Schleife
I
Unterschied: Die Bedingung wird nach einem Schleifenduchlauf geprüft
I
Damit der Compiler weiß, dass eine Schleife beginnt, wird zu Schleifenbeginn das
Schlüsselwort do gesetzt
int main ()
{
int xa [ arraysize ], i =0;
while (i < arraysize ){
xa [ i ]= i * i;
i = i +1;
}
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Schleifen und Felder
I
10 / 31
do i=i+1; while(i<10);
/ * 0 ,1 ,... ,11
*/
/ * square of index * /
Schleifenkörper
i =0;
while (i < arraysize ){
/ * 0 ,1 ,... ,11
*/
printf ( " Element %d of xa : % d \ n " ,i , xa [ i ]);
i = i +1;
}
return 0;
Bedingung
I
Wieder müssen bei mehr als einer Anweisung im Schleifenkörper diese in
geschweifte Klammern gesetzt werden
I
do-while-Schleife werden immer dann eingesetzt, wenn der Schleifenkörper
mindestens einmal ausgeführt werden soll
}
WS 2016/17 · M. Werner
11 / 31
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
12 / 31
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Beispiele für for-Schleife
for-Schleife
I
Typisch:
I Vor einer Schleife wird ein Wert initialisiert
I Im Schleifenkörper wird ein (meist derselbe) Wert geändert
I
Die for-Schleife lässt beides explizit in der Schleifendeklaration zu
I
Wieder: Mehr als ein Statement im Schleifenkörper muss geklammert werden
Achtung: Der Schleifenkörper kann leer sein á einzelnes Semikolon
I Schleifenkörper im Schleifenkopf integriert
I Schlechter Stil, außer bei sehr einfachen Schleifen
Initialisierung
/ * for .c -- loop with for * /
# include < stdio .h >
int main ( int argc , char * argv []){
for ( int i =0; i < argc ; i=i +1)
printf ("%d. argument : %s\n" ,i +1 , argv [i ]);
return 0;
}
I
for(int i=0;i<10; i=i+1) printf("i=%d \n",i);
Bedingung
Schleifenkörper
nach Schleifenkörper
WS 2016/17 · M. Werner
13 / 31
> ./for 23 foo Bar 42
1. argument: ./for
2. argument: 23
3. argument: foo
4. argument: Bar
5. argument: 42
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Es können einzelne Ausdrücke
weggelassen werden...
I
break und continue
... oder auch alle Ausdrücke á
Endlosschleife
/ * for2 . c -- loop with for , #2 * /
# include < stdio .h >
/ * for - ever .c -- infinite loop * /
# include < stdio .h >
int main ( int argc , char * argv []){
int i =0;
for (; i < argc ; i = i +1)
printf ( " % d . argument : % s \ n " ,
i +1 , argv [ i ]);
int main (){
for (;;)
printf (" The answer is 42.\ n" );
return 0;
// never reached
}
return 0;
I
Schleifen werden solange durchlaufen, wie die Schleifenbedingung gegeben ist
I
Allerdings gibt es zwei Möglichkeiten, innerhalb des Schleifenkörpers den
Kontrollfluss zu ändern:
break: Beendet die Schleife unabhängig von der Schleifenbedingung
continue: Startet sofort die nächste Auswertung der Schleifenbedingung und
ggf. den nächsten Schleifendurchlauf
Achtung!
Die Benutzung von break und continue ist eigentlich nicht notwendig und ein Indiz, dass die
Programmlogik nicht hinreichend durchdacht wurde.
Daher sollten break und continue nur zur Behandlung von Notfällen (Ausnahmen) genutzt
werden.
}
WS 2016/17 · M. Werner
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Beispiele für for-Schleife (Forts.)
I
14 / 31
15 / 31
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
16 / 31
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
break und continue (Forts.)
Geschachtelte Schleifen
/ * reciprocal . c -- calculate reciprocal value of array elements * /
# include < stdio .h >
I
Schleifen können auch ineinander verschachtelt sein
I
Dabei können sich die Schleifen auch beeinflussen
/ * a negative value indicates end of list * /
double f []={1.0 , .5 , 3.1415 , .33333 , 0.0 , 2.7182 , 42.23 , -1};
/ * for3 .c -- nested loops * /
# include < stdio .h >
int main ()
{
int i ;
for ( i =0; ; i = i +1){
if (f [i ] <0.0) break ;
if (f [i ] <=0.0001) continue ;
f [ i ]=1/ f [ i ];
}
int main ( int argc , char * argv []){
int goal ;
if ( sscanf ( argv [1] , "%d" ,& goal )!=1) return -1;
for ( int i =1; i <= goal ; i=i +1)
{
for ( int j =1; j <= i; j=j +1)
printf ("%d " ,i );
printf ( "\n" );
}
return 0;
for ( i =0; f [ i ] >=0.0; i = i +1)
printf ( " % d value : % f \ n " ,i , f [ i ]);
return 0;
}
}
WS 2016/17 · M. Werner
17 / 31
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
I
Schleifensteuerung
In Python gibt es zwei Arten von Schleifen:
I while-Schleifen
I for-Schleifen
I
Auch Python kennt die Schlüsselwörter break und continue
I
Die Semantik ist gleich zu C
I
Zusätzlich gibt es bei Python-Schleifen einen optionalen else-Zweig
á Wird nach der Schleife ausgeführt, wenn diese nicht abgebrochen wurde
while-Schleifen ähneln ihren Pendants in C:
i =10
while (i >0):
print (" i= " ,i)
i =i -1
I
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Schleifen in Python
I
18 / 31
Wie immer in Python können Blöcke durch Einrückungen markiert werden
WS 2016/17 · M. Werner
19 / 31
osg.informatik.tu-chemnitz.de
def prim ( x ):
y= int (x /2)
while y >=2:
if x % y == 0:
print (x , " has factor " , y)
break
y =y -1
else :
print (x , " is prim ")
WS 2016/17 · M. Werner
20 / 31
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Schleifensteuerung (Forts.)
for-Schleife in Python
Die Syntax for-Schleife sieht zunächst ähnlich wie die while-Schleife aus
I
I
Mit Hilfe von break kann leicht die do-while-Schleife aus C nachempfunden
werden
for i in C:
do _ something (i)
i =0
while True :
print (" i= " ,i)
i = i +1
if not (i <10): break
print ( " Ende " )
Die Semantik ist jedoch anders:
I C muss eine Sequenz oder Menge sein (d.h. String, Liste, Tupel, Menge,
Dictionary)3
I Es werden i nacheinander die Elemente von C zugewiesen
I
3 Genauer: Es muss ein iterierbarer Typ sein.
WS 2016/17 · M. Werner
21 / 31
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
for-Schleife in Python (Forts.)
for-Schleife in Python (Forts.)
Um die Semantik der C-for-Schleife nachzuempfinden, kann die range-Funktion
genutzt werden
I
# for . py -- loops over sequence objects
for x in [ ’ John ’ , ’ Paul ’ ,’ Georg ’ , ’ Pete ’ ]:
print (x )
I
22 / 31
range(start=0, end, step=1 )
Dies funktioniert auch für gemischte Typen:
Von
Bis
(nicht einschliesslich)
Schrittweite
»> range(5), range(2,5), range(2,10,2)
([0, 1, 2, 3, 4], [2, 3, 4], [2, 4, 6, 8])
»>
# for2 . py -- mixed types
T =( ’ Alpha ’ ,2 ,(1 ,2))
for x in T :
print (2 * x)
# for3 . py -- loops with range
python for2.py
AlphaAlpha
4
(1, 2, 1, 2)
WS 2016/17 · M. Werner
for i in range (1 ,8):
for j in range (i ):
print (i , end = ’ ’)
print ()
23 / 31
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
24 / 31
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.2 Schleifen in C und Python
Algorithmen und Programmierung – Iterationen
4.3 Iteration und Rekursion
Iteratoren in C
I
I
Umgekehrt kann man auch
den Python-Ansatz in C
„nachempfinden“
Solche Iteratoren sind z.B. in
C++ verbreitet
á Dort aber eleganter (auch in
C geht es schöner )
4.3 Iteration und Rekursion
/ * iter . c -- iterator with C * /
# include < stdlib .h >
# include < stdio .h >
I
Bisher wurden in Schleifen immer (implizite) Zuweisungen benutzt á
Zustandsmodell
I
Auch im funktionalen Modell sind Schleifen möglich
Dort werden sie durch Rekursion realisiert
I
static int ndx =0;
char * first () { return names [ ndx =0]; }
char * next (){
if ( names [ ndx ]== NULL ) ndx =0;
else ndx = ndx +1;
return names [ ndx ];
}
/ * recursion .c -- loops by recursion * /
# include < stdio .h >
void say _ it ( int i ){
if (i ==0) return ;
else {
printf ( " Cthulhu !\ n" );
say _ it (i -1);
}
}
char * names []={ " John " ," Paul " ," Georg " ,
" Ringo " , NULL };
int main (){
for ( char * str = first (); str != NULL ;
str = next ())
printf ( " %s " , str );
return 0;
}
WS 2016/17 · M. Werner
25 / 31
int main (){
say _ it (3);
return 0;
}
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
Algorithmen und Programmierung – Iterationen
4.3 Iteration und Rekursion
I
Dabei kann der
Schleifenkörper von
der
„Schleifenmechanik“
getrennt werden, so
dass eine
Schleifenfunktion
möglich ist
Wir nutzen hier
einen Zeiger auf
Funktionen
Schleifenfunktion (Forts.)
I
/ * loop - func . c * /
# include < stdio .h >
Allgemeiner (und in der Anwendung eleganter) funktioniert dies in Python, das mit
λ-Funktionen (namenlosen Funktionen) ein Feature funktionaler Sprachen bietet
// Pointer to a void function with integer argument
typedef void ( * VFP )( int );
void loop ( VFP func , int start , int end ,
unsigned int step ){
if ( start <= end ) {
func ( start );
loop ( func , start + step , end , step );
}
}
void lbody ( int param ){
printf ( " % d ^2=% d \ n " , param , param * param );
}
int main (){
loop ( lbody ,0 ,10 ,1);
return 0;
}
WS 2016/17 · M. Werner
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.3 Iteration und Rekursion
Schleifenfunktion
I
26 / 31
27 / 31
osg.informatik.tu-chemnitz.de
# loop - func . py -- loops by recursion
from sys import stdout
loop = lambda v ,e ,i ,f , args : \
e (v) and (f ( * (( v ,)+ args )) , \
loop (( lambda y: y+i )( v),e ,i ,f , args )) or 0
def printpow (i ,x ):
print (i ," ** " ,x ,"=" ,i ** x)
>python loop-func.py
1 ** 2 = 1
2 ** 2 = 4
3 ** 2 = 9
4 ** 2 = 16
[10] [9] [8] [7] [6] [5] [4] [3]
[2] [1] [0]>
def printi (i ,b ,a ): stdout . write (b+ str (i )+ a)
loop (1 , lambda x: x <=4 ,1 , printpow ,(2 ,))
loop (10 , lambda x: x >=0 , -1 , printi , ("[" ,"] " ))
WS 2016/17 · M. Werner
28 / 31
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
4.3 Iteration und Rekursion
Algorithmen und Programmierung – Iterationen
4.3 Iteration und Rekursion
Äquivalenz
I
Äquivalenz (Forts.)
Allgemein gilt:
Jede Schleife in einem Programm kann in eine rekursive Funktion umgewandelt
werden.
I
Schleifen und Rekursion sind also für die meisten praktischen Anwendungsfälle
gleichmächtig
I
In der Regel ist eine Schleife übersichtlicher
I
Es gibt aber auch Fälle (vgl. Kapitel 9), in denen Rekursion die handlichere Lösung
bildet
I
Einige Programmiersprachen kennen keine Schleifen, sondern nur Rekursionen
und
Jede (trivial-)rekursive Funktion kann mit Hilfe von Schleifen berechnet
werden.Genauer: Primitiv-rekursive Funktionen lassen sich stets mit a priori
beschränkten Schleifen berechnen; bei sogenannten µ-rekursive Funktionen muss
diese Einschränkung aufgegeben werden.
I
Nicht trivialerekursiv
ist z.B. die ACKERMANN-Funktion:

f (x, y) =

⇐x=0
y + 1
f (x − 1, 1)
⇐ (x 6= 0) ∧ (y = 0)


f (x − 1, f (x, y − 1)) sonst
WS 2016/17 · M. Werner
29 / 31
osg.informatik.tu-chemnitz.de
Algorithmen und Programmierung – Iterationen
Aufgaben
Aufgaben
Aufgabe 4.1
Was bedeutet in C die folgende Deklaration:
int* (*foo)(int,int*)
Aufgabe 4.2
In einer Schale und in einem Eimer seien eine Anzahl von weißen und orangen Tischtennisbällen,
wobei soviel Bälle im Eimer sind, dass der folgende Algorithmus stets durchgeführt werden kann:
1. Nehme zwei beliebige Bälle aus der Schale.
I
I
Wenn sie die gleiche Farbe haben, werfe sie in den Eimer und nehme einen orangen
Ball aus dem Eimer und lege ihn in die Schale.
Wenn sie unterschiedliche Farbe haben, lege den weißen in die Schale zurück und
werfe den orangen Ball in den Eimer.
2. Wiederhole, bis nur noch ein Ball in der Schale ist.
Wird tatsächlich stets ein Ball übrig bleiben? Wenn ja, kann etwas über seine Farbe in
Abhängigkeit zur ursprünglichen Anzahl der Bälle gesagt werden? Wenn ja, was?
WS 2016/17 · M. Werner
31 / 31
osg.informatik.tu-chemnitz.de
WS 2016/17 · M. Werner
30 / 31
osg.informatik.tu-chemnitz.de
Herunterladen