Récursivité NF01 Philippe TRIGANO NF01 Définition Une fonction ou une procédure est dite récursive s’il est fait appel à cette fonction ou à cette procédure dans le corps d'instructions qui la définit. En d’autres termes , la fonction (ou la procédure) s'appelle elle-même NF01 Exemple Fonction factorielle n! = n*(n-1)* …….1 Mais aussi • n! =n*(n-1)! • function factorielle(n:integer): longint; begin if (n > 1) then factorielle:= n * factorielle (n-1) else factorielle:= 1; end; NF01 Somme des n premiers nombres Fonction itérative : function somme(N:integer):longint; var i : integer; sum : longint; begin sum:=0; for i := 1 to N do sum := sum + i; somme := sum; end; NF01 Somme des n premiers nombres Fonction récursive S(n) = S(n - 1) + n S(0) = 0 pour la condition d'arrêt NF01 program SommePremiersEntiers ; var n:integer; function somme ( n : integer ) : integer ; begin if n = 0 then somme:= 0 else somme:= somme (n - 1) + n; end; begin readln(n); writeln(somme (n)); end. somme(4) début appel de somme avec n = 3 {début de l'empilement} début appel de somme avec n = 2 début appel de somme avec n = 1 début appel de somme avec n = 0 {fin de l'empilement} début somme 0 fin {début du dépilement} somme somme (0) + 1 = 0 + 1 = 1 fin somme somme (1) + 2 = 1 + 2 = 3 fin somme somme (2) + 3 = 3 + 3 = 6 fin somme somme (3) + 4 = 6 + 4 = 10 Fin {fin du dépilement} Résultat : somme (4) = 10 Fin program A_Trouver ; const POINT = '.' ; procedure Faire ; var car : char ; begin readln (car) ; if car <> POINT then Faire ; write (car) ; end; { programme principal } begin writeln ('Entrez un texte') ; Faire ; writeln; end. Exécution : B o n j o u r . Affichage : .ruojnoB appel de FAIRE lire (car) : car = ‘B’ car<> ‘.’ appel de FAIRE { empilement (CAR = ‘B’) } lire (CAR) : car = ‘o’ car <> ‘.’ appel de FAIRE { empilement (CAR = ‘o’) } lire (CAR) : car = ‘n’ car <> ‘.’ appel de FAIRE { empilement (CAR = ‘n’) } lire (CAR) : car = ‘.’ car = ‘.’ => on n’exécute pas la partie « then » write(CAR) => affichage de ‘.’ fin { dépilement (CAR = ‘n’) } write(CAR) => affichage de ‘n’ fin { dépilement (CAR = ‘o’) } write(CAR) => affichage de ‘o’ fin { dépilement (CAR = ‘B’) } write(CAR) => affichage de ‘B’ fin { dépilement (CAR n’existe plus, variable LOCALE) } Affichage : ‘.noB’ NF01 Exercice Ecrire une fonction récursive permettant de calculer cos(x) et sin(x) Principe ? • Exprimer en fonction du cosinus et/ou du sinus d’un nb plus petit Condition d’arrêt ? NF01 Algorithme sinus Si x est petit alors sin(x) ← x Sinon sin(x) ← 2 sin(x/2) * cos(x/2) cosinus Si x est petit cos(x) ← 1 Sinon cos(x)=cos2(x/2) - sin2(x/2) NF01 function cosinus(x: real):real; forward; {voir plus loin} function sinus(x: real):real; begin if x <= 0.00001 then sinus := x else sinus := 2 * sinus(x/2) * cosinus(x/2) end; function cosinus(x: real):real; begin if x <= 0.00001 then cosinus := 1 else cosinus := sqr(cosinus(x/2))-sqr(sinus(x/2)) end; Tours de Hanoï BUT : Déplacer la pile de la tour 1 à la tour 3, en ne déplaçant qu'un disque à la fois, et en s'assurant qu’aucun disque ne repose sur un disque de plus petite dimension. NF01 La véritable histoire des tours de Hanoï Il y a fort longtemps, Zeus décida de punir Apollon car ce dernier passait trop de temps à courir les jupons. Il l'appela et lui dit : Tu devras aller à Hanoï et trouver trois piliers : sur celui de gauche, j'ai posé 9 disques d'or, par ordre décroissant de taille. Tu les déplaceras sur le pilier de droite, dans le même ordre ! No problem ! répondit le fier Apollon. N'interromps pas le grand Zeus ! Tu devras déplacer un seul disque à la fois. Et ne place jamais un disque sur un autre de taille plus petite. Mais à quoi sert le pilier du milieu ? Idiot ! Sans la voie du milieu, toute tâche est impossible. Car tu dois d'abord poser un disque sur l'un des piliers, avant de pouvoir en prendre un autre. Si tu commets une erreur, tu devras tout recommencer, depuis le début ! Trois mille ans plus tard, les disques d'or étaient toujours sur le pilier de gauche. Apollon avait échoué. Zeus lui rendit une petite visite et lui dit : Pourquoi n'utilises-tu pas la récursivité ? Tiens, voilà un micro-ordinateur avec un compilateur Pascal. A toi de jouer... Et tâche de réussir cette fois... Merci à Paul Yves Gloess pour cette petite histoire, tirée de son livre 'Understanding LISP' (An Alfred Handy Guide, Alfred Publishing Co, Sherman Oaks, 1982). NF01 Tours de Hanoï BUT : Déplacer la pile de la tour 1 à la tour 3, en ne déplaçant qu'un disque à la fois, et en s'assurant qu’aucun disque ne repose sur un disque de plus petite dimension. NF01 Algorithme Hypothèse : on veut déplacer la pile des n-1 premiers disques de la tour 1 à la tour 2 Action : Déplacer le dernier disque de la tour 1 à la tour 3 Ensuite : il ne reste plus qu’à déplacer les n-1 disques de la tour 2 à la tour 3 Condition d’arrêt : nb de disques = 0 (il n’y a plus de disque à déplacer) NF01 Ecriture en Pascal procedure Hanoi (nbDisques ,T_orig,T_dest,T_inter: integer); begin if (nbDisques > 0) then begin Hanoi (nbDisques - 1 , T_orig, T_inter, T_dest) ; writeln ('Déplacer le disque de ', T_orig,' à ', T_dest); Hanoi (nbDisques - 1 , T_inter, T_dest, T_orig) ; end; end; NF01