TD7 Correction
TD7 Correction
TD7 Correction
TD n◦7 - Correction
Récursivité
On peut aussi tout écrire dans une seule méthode, mais celà va être moins lisible :
1
if (r > maxi)
r=maxi;
}
return r;
}
Dans les exercices sur la récursivité, l’usage de boucles for est interdit !
Exercice 2 Récursivité
1. Écrire une méthode récursive static int fact(int n) permettant de calculer la facto-
rielle de n.
Correction :
Attention : outre l’appel récursif, toutes les méthodes récursives doivent conteinir un critère d’arrêt.
S’il n’y a pas de critère d’arrêt ou s’il n’est pas bon, on va avoir une récursion à l’infini, qui va
provoquer une erreur à l’exécution. C’est par exemple le cas pour le code suivant :
static void stupide()
{
stupide();
}
où stupide() fait des appels en cascade d’elle-même sans jamais s’arrêter.
static int fact(int n)
{
if (n==0) return 1; //critère d’arr^
et
return n*fact(n-1); //appel récursif
}
2
static double exp(double x, int n)
{
if (n==0) return 1;
if (n%2==0)
{
double a=exp(x, n/2);
return a*a;
}
else
{
double a=exp(x, n-1/2);
return a*a*x;
}
}
Ainsi, pour calculer 237 , on aura des appels à exp(2, 37), exp(2, 18), exp(2, 9), exp(2, 4),
exp(2, 2), exp(2, 1), exp(2, 0).
En revanche si on utilisait une exponentiation naı̈ve :
static double expNaive(double x, int n)
{
if (n==0) return 1;
return x*exp(x, n-1);
}
le même calcul nécessiterait des appels à exp(2, 37),exp(2, 36),exp(2, 35), . . ., exp(2, 0), ce
qui est beaucoup plus couteux.
Dans le second cas, le calcul de xn a une complexité linéaire O(n), alors que dans le premier cas,
on peut montrer qu’elle est logarithmique (O(log(n))).
2. En utilisant une méthode récursive auxiliaire, écrire une méthode static affiche(int[] t)
permettant d’afficher le tableau t.
Correction :
Commençons par écrire une méthode permettant d’afficher les n premiers éléments d’un tableau.
Pour afficher les n premiers éléments, on affiche les n − 1 premiers, puis on affiche le nème .
static void afficheN(int n, int[] t)
{
if (n==0) return;
3
afficheN(n-1, t);
System.out.println(t[n-1]);
}
il ne reste plus alors qu’à afficher les t.length premiers éléments de t pour l’afficher entièrement.
static void affiche(int[] t)
{
afficheN(t.length, t);
}
3. Modifier la méthode précédente pour que le tableau soit affiché dans l’ordre inverse.
Correction :
Il suffit, dans afficheN d’afficher l’élément courant avant d’afficher ce qui précede :
static void afficheN(int n, int[] t)
{
if (n==0) return;
System.out.println(t[n-1]);
afficheN(n-1, t);
}
Exercice 4 On parle de récursivité croisée lorsque deux fonctions s’appellent l’une l’autre
récursivement.
Les fonctions suivantes sont censées donner la parité d’un nombre entier : cela sera-t-il le
cas pour toutes les valeurs entières positives ?
import fr.jussieu.script.Deug;
class PairImpair{
4
Correction : Regardons ce qui se passe lors d’un appel à pair(3). En suivant l’exécution du code pas
à pas, on va avoir les appels suivants :
pair(3)
impair(2)
pair(1)
impair(0)
pair(-1)
impair(-2)
...
La condition d’arrêt n’est donc pas bonne. Un autre élément montrant que ce code ne peut pas
marcher est qu’aucune des deux méthodes ne peut jamais renvoyer false.
On pourrait les modifier de la manière suivante pour qu’elles fonctionnent :
import fr.jussieu.script.Deug;
class PairImpair{
5
– On transfère le petit plateau de 0 à 1.
– On transfère le grand plateau de 0 à 2.
– On transfère le petit plateau de 1 à 2.
Si vous n’êtes pas convaincus, faites un dessin . . .
3. Supposez qu’un de vos amis sache résoudre le problème pour un certain n, et n’importe
quels i et j. On vous demande de résoudre le problème pour n + 1. Vous avez le droit
d’utiliser l’aide de votre ami. Comment vous y prenez-vous ?
Correction : On demande à l’ami de déplacer n plateaux de i à l’emplacement qui n’est ni i ni j.
On déplace ensuite le dernier plateau (le plus gros) de i à j. On remet à contribution l’ami pour
déplacer les n plateaux vers j.
4. Écrire un algorithme récursif void hanoi(int n, int i, int j) affichant la suite des
instructions à effectuer pour résoudre le problème.
Par exemple hanoi(2, 0, 2) devra renvoyer
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
Correction :
Nous allons écrire une fonction auxiliaire pour trouver le numéro de l’emplacement qui n’est ni i
ni j :
static int autre(int i, int j)
{
if (i==0)
{
if (j==1)
return 2;
else
return 1;
}
else
if (i==1)
{
if (j==0)
6
return 2;
else
return 0;
}
else
{
if (j==0)
return 1;
else
return 0;
}
}
On déduit l’algorithme de la question ci-dessus, sans oublier la condition d’arrêt.
static void hanoi(int n, int i, int j)
{
if (n==1)
{
System.out.println(¨Déplacer un plateau de ¨+i+¨ à ¨+j);
return;
}
int a=autre(i, j);
hanoi(n-1, i, a);
System.out.println(¨Déplacer un plateau de ¨+i+¨ à ¨+j);
hanoi(n-1, a, j);
}
À titre d’exemple, voici la liste des instructions pour déplacer 6 plateaux de 0 à 2 :
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
Déplacer un plateau de 0 à 1
Déplacer un plateau de 2 à 0
Déplacer un plateau de 2 à 1
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
Déplacer un plateau de 1 à 0
Déplacer un plateau de 2 à 0
Déplacer un plateau de 1 à 2
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
Déplacer un plateau de 0 à 1
Déplacer un plateau de 2 à 0
Déplacer un plateau de 2 à 1
Déplacer un plateau de 0 à 1
Déplacer un plateau de 2 à 0
Déplacer un plateau de 1 à 2
Déplacer un plateau de 1 à 0
Déplacer un plateau de 2 à 0
Déplacer un plateau de 2 à 1
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
7
Déplacer un plateau de 0 à 1
Déplacer un plateau de 2 à 0
Déplacer un plateau de 2 à 1
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
Déplacer un plateau de 1 à 0
Déplacer un plateau de 2 à 0
Déplacer un plateau de 1 à 2
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
Déplacer un plateau de 1 à 0
Déplacer un plateau de 2 à 0
Déplacer un plateau de 2 à 1
Déplacer un plateau de 0 à 1
Déplacer un plateau de 2 à 0
Déplacer un plateau de 1 à 2
Déplacer un plateau de 1 à 0
Déplacer un plateau de 2 à 0
Déplacer un plateau de 1 à 2
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
Déplacer un plateau de 0 à 1
Déplacer un plateau de 2 à 0
Déplacer un plateau de 2 à 1
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
Déplacer un plateau de 1 à 0
Déplacer un plateau de 2 à 0
Déplacer un plateau de 1 à 2
Déplacer un plateau de 0 à 1
Déplacer un plateau de 0 à 2
Déplacer un plateau de 1 à 2
Je déconseille d’essayer ça chez vous. . .