Recursion

Werbung
Rekursive Algorithmen
Recursion
Ferd van Odenhoven
Fontys Hogeschool voor Techniek en Logistiek Venlo
Software Engineering
6. Oktober 2014
ODE/FHTBM
Recursion
6. Oktober 2014
1/18
Rekursive Algorithmen
1
ODE/FHTBM
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Recursion
6. Oktober 2014
2/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Anwendung mathematischer Relationen
Gegeben sei eine mathematische Funktion z. B. für Fakultät N:
N! = N ∗ (N − 1)!
,
N≥0
,
(0! = 1).
(1)
Programm:
static int factorial ( int N )
{
if ( N ==0) return 1;
return N * factorial (N -1);
}
ODE/FHTBM
Recursion
6. Oktober 2014
3/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Einige Anmerkungen
Dieselbe Berechnung ließe sich auch mit einer einfachen
for-Schleife durchführen.
Ein rekursives Programm lässt sich immer in ein
nicht-rekursives umwandeln und umgekehrt.
Manchmal ist es viel einfacher, ein rekursives Programm zu
entwerfen als eine korrekte Schleife.
ODE/FHTBM
Recursion
6. Oktober 2014
4/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Richtigkeit
Durch Induktion beweisen, dass die Rekursion funktioniert; z. B.
for N!:
static int factorial ( int N )
{
if ( N ==0) return 1;
return N * factorial (N -1);
}
Sie berechnet 0! (Grundschritt)
Da sie (N − 1)! berechnet, berechnet sie N! (Induktion)
ODE/FHTBM
Recursion
6. Oktober 2014
5/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Richtigkeit
Wir werden keine formalen Richtigkeitsbeweise verwenden, es
sollen nur zwei grundlegende Eigenschaften erfüllt sein:
Ein Basisfall muss explizit erfüllt sein (Grundschritt)
Rekursiver Aufruf mit kleineren Argumenten (Induktion)
In diesem Programm gibt es keine Induktion im oben definierten
Sinn:
static int puzzle ( int N )
{
if ( N == 1) return 1;
if ( N %2 == 0) return puzzle ( N /2);
else return puzzle (3* N +1);
}
ODE/FHTBM
Recursion
6. Oktober 2014
6/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Puzzle-Beispiel
puzzle (3)
puzzle (10)
puzzle (5)
puzzle (16)
puzzle (8)
puzzle (4)
puzzle (2)
puzzle (1)
ODE/FHTBM
Recursion
6. Oktober 2014
7/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Euklidischer Algorithmus
Finden Sie den größten gemeinsamen Teiler von zwei Zahlen M
und N, wobei M > N.
Wenn M und N einen gemeinsamen Teiler p haben, ist p auch
ein Teiler von (M mod N).
Der größte mögliche Wert von p ist N;
Wenn an irgend einer Stelle p gleich N ist, haben wir: (M
mod N) = 0, und der Algorithmus muss sich beenden!
ODE/FHTBM
Recursion
6. Oktober 2014
8/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Euklidischer Algorithmus: recursive method
/* *
* pre : M > N
* post : M = gcd (M , N )
*/
int gcd ( int M , int N )
{
if ( N ==0) return M ;
return gcd ( N , M % N );
}
ODE/FHTBM
Recursion
6. Oktober 2014
9/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Euklidischer Algorithmus: non recursive method
/* *
*
*
*/
int
{
pre : M > N
post : M = gcd (M , N )
gcd ( int M , int N )
int h ;
while ( N != 0)
{
h = N;
N = M % N;
M = h;
}
return M ;
}
ODE/FHTBM
Recursion
6. Oktober 2014
10/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Euklidischer Algorithmus
gcd (314159 , 271828)
gcd (271828 , 42331)
gcd (42331 , 17842)
gcd (17842 , 6647)
gcd (6647 , 4458)
gcd (4458 , 2099)
gcd (2099 , 350)
gcd (350 , 349)
gcd (349 , 1)
gcd (1 ,0)
ODE/FHTBM
Recursion
6. Oktober 2014
11/18
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Rekursive Algorithmen
Baum für arithmetischer Ausdruck
×
+
5
×
7
×
+
9
8
4
6
Abbildung : Beispiel: Baum für arithmetischer Ausdruck
ODE/FHTBM
Recursion
6. Oktober 2014
12/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Präfix-Ausdrücke evaluieren
Das rekursive Programm evaluiert die Präfix-Ausdrücke aus dem
vorangehenden Kapitel, z. B.:
∗ + 7 ∗ ∗ 4 6 + 8 9 5
Die Überlegung ist: Die Rekursion im linken Baum und im rechten
Baum werden gleichzeitig initiiert! Die nächste Folie zeigt Details.
Vorsicht! Gültige arithmetische Operationen sind + und ∗, aber
nicht − oder /.
ODE/FHTBM
Recursion
6. Oktober 2014
13/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Programm eval
int eval ()
{
int i = 0;
int x = 0;
if ( expr [ i ] == ’+ ’) {
i ++;
return eval () + eval ();
}
if ( expr [ i ] == ’* ’) {
i ++;
return eval () * eval ();
}
while (( expr [ i ] >= ’0 ’) && ( expr [ i ] <= ’9 ’ )) {
x = 10* x + ( expr [ i ++] - ’0 ’ );
}
return x ;
}
ODE/FHTBM
Recursion
6. Oktober 2014
14/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Präfix-Beispiel
eval () * + 7 * * 4 6 + 8
eval () + 7 * * 4 6 + 8
eval () 7
eval () * * 4 6 + 8 9
eval () * 4 6 + 8
eval () 4
eval () 6
return 24 = 4*6
eval () + 8 9 5
eval () 8
eval () 9
return 17 = 8+9
return 408 = 24*17
return 415 = 7+408
eval () 5
return 2075 = 415*5
ODE/FHTBM
Recursion
9 5
9 5
5
9 5
6. Oktober 2014
15/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Schlussbemerkungen: Rekursionen und Bäume
Die Tiefe der Rekursion: ist die maximale Verschachtelungstiefe
und hängt ab von der Eingabe.
Rekursive Programme: brauchen eine Stackmaschine, deren
Speicherverbrauch proportional ist zur Tiefe der
Rekursion.
Datenstrukturen: sind inhärent rekursiv, wenn die Objekte darin
auf ein oder mehrere Objekte vom selben Typ
verweisen.
Rekursive Programme: sind deshalb die Implementierungen, die
sich für solche Datenstrukturen, z. B. verkettete
Listen, anbieten.
Beachten Sie: dass die Tiefe der Rekursion der Länge einer
verketteten Liste entsprechen kann.
ODE/FHTBM
Recursion
6. Oktober 2014
16/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Rekursive Funktionen für verkettete Listen 1
int count ( Node h ) {
if ( h == null ) return 0;
return 1 + count ( h . next );
}
void traverse ( Node h ) {
if ( h == null ) return ;
h . item . visit ();
traverse ( h . next );
}
ODE/FHTBM
Recursion
6. Oktober 2014
17/18
Rekursive Algorithmen
Anwendung mathematischer Relationen
Richtigkeit
Beispiele
Schlussbemerkungen
Rekursive Funktionen für verkettete Listen 2
void traverseR ( Node h ) {
if ( h == null ) return ;
traverseR ( h . next );
h . item . visit ();
}
Node remove ( Node h , Item v ) {
if ( h == null ) return null ;
if ( eq ( h . item , v )) return remove ( h . next , v );
h . next = remove ( h . next , v );
return h ;
}
ODE/FHTBM
Recursion
6. Oktober 2014
18/18
Herunterladen