Title: R
1 La récursivité
Une procédure est dite récursive si, et seulement
si, elle fait appel à elle-même, soit directement
soit indirectement
Djamal Rebaïne
1
2(No Transcript)
3Un exemple
- (vision itérative) Un escalier de hauteur h
cest une séquence de h marches - (vision
récursive) Un escalier de hauteur h cest une
marche suivie dun escalier de hauteur h - 1
4- Version itérative
- static void monter_escalier( int h )
-
- for (int i 1 i lt h i)
- monter_marche()
-
- Version récursive
- void monter_escalier( int h )
-
- if (h gt 0)
- monter_marche()
- monter_escalier( h-1 )
5Récursivité en action Que fait lappel monter
escalier( 3 ) ? monter_escalier( 3 )
monter_marche() monter_escalier( 2
) monter_marche()
monter_marche() monter_escalier( 1 )
monter_marche() monter_marche()
monter_marche() Même effet que la version
itérative, cest-à-dire 3 appels à monter marche()
6Recette de récursivité Sassurer que le
problème peut se décomposer en un ou plusieurs
sous-problèmes de même nature Identifier le
cas de base qui est le plus petit problème qui ne
se décompose pas en sous-problèmes Résoudre(P)
si P est un cas de base, le résoudre
directement sinon
décomposer P en sous-problèmes P1, P2,...
résoudre récursivement P1, P2,...
combiner les résultats obtenus pour P1, P2,
, pour obtenir la solution pour
avoir la solution au problème de
départ.
7Fonctionnement dune fonctionrécursive
- Création dune pile pour la sauvegarde entre
autres des paramètres dappels de la procédure et
la ladresse de retour.
8- Calculer le factoriel de n, noté n!
- Le problème est Calculer le factoriel d'un
nombre entier donné en entrée. - En entrée Nous avons n nombre entiers qui sont
plus grands ou égaux à 0. - Sortie Nous avons un nombre entier qui
représente le factoriel de n.
9- Fonction principale
- entier n nfact
- lire n
- si (n lt 0) alors écrire entrée négative n
- sinon
- nfact factoriel(n)
- écrire la factorielle de n est nfact
- où factoriel satisfait le prototype
- entier factoriel(entier)
10Fonction factoriel int factoriel(entier n)
si (n lt 1) retourner 1 retourner n
factoriel(n-1)
11Comment le faire en assembleur?
- On a besoin dune pile!
- En effet, à chaque appel récursif, la valeur du
paramètre n est sauvegardée dans la pile de
travail. - Ce processus dempilement est répété jusquà ce
que le paramètre actuel (de lappel) n atteigne
la valeur 0. Cela correspond à la fin de
lexécution de la fonction appelante. - Ensuite, commence le dépilement, et lexécution
de la prochaine instruction de la fonction
appelante est entamée. Ce processus de dépilement
est répété jusquà ce quon atteigne la valeur de
départ du paramètre n.
12Cela se traduit par le programme assembleur
suivant
TITLE factoriel PILE segment stack dw
100 dup(?) Basdepile equ this word PILE
ends Data segment N dw 4 fact dw
? Data ends Code segment assume CScode,
DSData, SSPile Debut MOV AX,Data
MOV DS,AX MOV AX,Pile MOV SS, AX
initialise le segment de pile MOV SP,
basdepile copier l'adresse de la base de la
pile dans SP mov BX,n sauvegarde la
valeur de n mov AX,BX Push AX call
factoriel Fin pop AX le
résultat calculé par la fonction factoriel est
dans AX mov fact, AX mov
AX,4c00h int 21h
Djamal Rebaine
13Factoriel proc near en utilisant la pile
CMP AX,0 JA DEPILE MOV AX,1
JMP fin DEPILE dépiler
jusquà ce n 0 DEC AX PUSH AX
factoriel(n-1) CALL FACTORIAL
RetourResultat POP BX MUL BX
fin ret factoriel endp fin de la
procédure code ends end debut fin du
programme code
14Calcul dune somme par récursivité
Title sommerecursive pour totaliser la somme de
1 jusquà n. PILE segment stack dw 100
dup(?) Basdepile equ this word PILE
ends Data segment N dw 12 som dw
? Data ends Code segment assume CScode,
DSData, SSPile Debut MOV AX,Data
MOV DS,AX MOV AX,Pile MOV SS, AX
initialise le segment de pile MOV SP,
basdepile copier l'adresse de la base de la
pile dans SP
Djamal Rebaïne
14
15mov CX,n sauvegarde la valeur de n XOR
AX,AX CALL sommerecursive Fin
pop AX le résultat calculé par la
fonction factoriel est dans AX mov
fact, AX mov AX,4c00h int 21h
16- sommerecursive proc near
- CMP CX,0
- JNZ fin
- mov cx, 0
- Fin push cx
- dec cx
- CALL sommerecursive resultat est dans cx
- pop ax
- add ax,cx
- fin ret
- factoriel endp fin de la procédure
- code ends
- end debut fin du programme code
17Inversion dune chaine de caractères
- Donnée S une chaine de caractères
- Question Afficher S dans le sens inverse
18- Fonction principale
- ecrire introdroduire la chaîne
- inverser
19Fonction factoriel Entête entier
factoriel(entier n) Corps lire car si
car ltgt . inverser afficher
car
20- La fonction inverser fonctionne comme suit
- Tant que le caractère lu nest pas le point,
- continuer la lecture
- Arrivé au point, laffichage commence.
21- TITLE INVERSER-CHAINE
- affiche macro chaine
- mov dx,offset chaine
- mov ah, 09h
- int 21h
- endm
- PILE segment stack
- dw 100 dup(?)
- Basdepile equ this word
- PILE ends
- Data segment
- Chaine db introduire votre chaine, 10,13,
- Data ends
- Code segment
- assume CScode, DSData, SSPile
- Debut
- MOV AX,Data
- MOV DS,AX
22- inverser Proc near les appels récursifs sont
gérés exclusivement par la pile. - mov ah,1 lecture dun caractère
- int 21h
- CMP AL,.
- JNE dépiler dépiler jusquà ce AL .
- CBW convertir le caractère en un
mot - ou alors faire mov
AH,0 - push AX
- inverser
- Depiler POP AX
- mov AH,2
- int 21
- ret
- inverser fin de la procédure
- code ends fin du programme principal
- end debut
23- inverser Proc near dans cette version, les
appels récursifs sont gérés -
exclusivement par la pile. - Continuer
- mov ah,1 lecture dun
caractère - int 21h
- CMP AL,.
- JNE dépiler dépiler jusquà ce AL
. - CBW convertir le
caractère en un mot - ou alors faire
mov AH,0 - push AX
- JMP continuer
- Depiler POP AX
- mov AH,2
- int 21
- JMP depiler
- ret
- inverser fin de la procédure
24- Rechercher lélément C dans un tableau trié dans
lordre croissant.
A
..
C?
milieu
u
L
25- Int void recherche(C,L,uentier trouvebooleen)
-
- si (u lt L)
- milieu (u - L 1) div 2
- si Amilieu C
- return (milieu)
- sinon si Amilieu gt C
-
recherche(C,L,milieu-1) - sinon
recherche(C,milieu1,u) -
- sinon return (-1)
-
26- TITLE dichotomique
- PILE segment stack
- dw 100 dup(?)
- Basdepile equ this word
- PILE ends
- Data segment
- tableau db 1, 4, 8, 10, 18
- Donnee db 18
- Data ends
- Code segment
- assume CScode, DSData, SSPile
- Debut
- MOV AX,Data
- MOV DS,AX
- MOV AX,Pile
- MOV SS, AX initialise le segment de pile
- MOV SP, basdepile copier l'adresse de la
base de la pile dans SP - Lea SI, tableau
27- Dichoto proc near
- pop SI
- pop BX
- CMP SI,BX
- JL fin continuer jusquà
il ny ait plus délément à rechercher - mov AX, BX
- ADD AX, SI
- Sub AX, 1
- Mov DL,2
- DIV DL
- CBW
- Mov CX,SI
- Mov SI, AX
- CMP SI, donnee
- jne appel
- mov AX,SI
- ret
- Appel jg autreappel
- push BX
28Les nombres de Fibonacci
- Question Écrire un programme qui calcule le
nombre de Fibonacci défini comme suit
29- TITLE fibonacci
- SPILE SEGMENT STACK
- DW 100 DUP(?)
- SPILE ENDS
- SDATA SEGMENT
- n dw 6
- SDATA ENDS
- SCODE SEGMENT
- ASSUME CSSCODE,DSSDATA
- DEBUT
- mov ax,sdata
- mov ds,ax
- xor ax,ax
- xor bx,bx
- mov ax,n
- call fibo
- mov dl,al
- add dl,30h
- mov ah,2
30- Fibo proc
- si1
- cmp ax, 1 comparer ax avec 1
- ja else si nlt 1,
retourner 1 - mov ax, 1 mettre 1 dans ax
- ret
- else
- dec ax décrémenter ax
de 1 c'est-à-dire égal à n-1 - push ax mettre n-1 sur la
pile - call Fibo résultat dans ax
- pop bx rectifier la
pile et bx n-1 - dec bx bx n -2
- push ax sauvegarder ax
Fibonacci(n-1) sur la pile - mov ax,bx passe le n-1 à ax
pour exécuter Fibonacci(n-2) - call Fibo résultat dans ax
Fibonacci(n-2) - pop bx bx
Fibonacci(n-1) - add ax, bx ax
Fibonacci(n-2) Fibonacci(n-1) - ret
- Fibo endp
31Les tours de Hanoï
http//www.multimania.com/fmaire/jeux/han
oi/hanoi.html http//members.aa.net/wgf/Hanoi/H
anoi.html
32- Description du problème Montrez comment déplacer
n disques de tailles distinctes d'une tige A vers
une tige B - en utilisant comme tampon une tige C.
Initialement seule la tige A contient les n
disques ordonnés avec le plus petit sur le
dessus. On ne doit déplacer qu'un seul disque à
la fois. Il est interdit de placer un disque sur
un autre plus petit.
33- Entrée Un entier n représentant le nombre de
disques. - Sortie Une série d'instructions de la forme "
déplacer i vers j" indiquant les déplacements
nécessaires pour résoudre le problème.
34- Fonction principale
- entier n
- lire n
- hanoi(n,1,2,3)
- où hanoi satisfait le prototype
- hanoi(entier, entier, entier, entier)
35- Supposons quon sache comment déplacer les (n-1)
derniers disques de la tour 1 vers la tour 2, en
utilisant la tour 3. - déplacer le disque restant de la tour 1 vers la
tour 2 - déplacer maintenant les (n-1) disques de la tour
3 vers la tour 2, en saidant de la tour 1.
36- Fonction hanoi
- Entête
- hanoi(entier n, entier i, entier j, entier k)
- (Affiche les instructions pour déplacer n
disques - de la tige i vers la tige k)
- Corps
- si (n gt 0)
-
- hanoi(n-1, i, k, j)
- écrire "Déplacer i vers k)
- hanoi(n-1, j, i, k)
-
37- include ltiostream.hgt
-
- void hanoi (int,int,int,int)
- void hanoi(int n,int i,int j,int k)
-
- if (ngt0)
-
- hanoi(n-1,i,k,j)
- cout ltltdéplacer le disque de haut de la
tourltltiltlt à la tour ltltk - hanoi(n-1,j,k,i)
-
- main()
-
- int n
- cingtgtn
- hanoi(n,1,2,3)
-
38Exemple avec n 4 disques
- On obtient la série daffichages suivants
- Déplacer le disque de haut de la tour 1 à la tour
2 - Déplacer le disque de haut de la tour 1 à la tour
3 - Déplacer le disque de haut de la tour 2 à la tour
3 - Déplacer le disque de haut de la tour 1 à la tour
2 - Déplacer le disque de haut de la tour 3 à la tour
1 - Déplacer le disque de haut de la tour 3 à la tour
2 - Déplacer le disque de haut de la tour 1 à la tour
2 - Déplacer le disque de haut de la tour 1 à la tour
3 - Déplacer le disque de haut de la tour 2 à la tour
3 - Déplacer le disque de haut de la tour 2 à la tour
1 - Déplacer le disque de haut de la tour 3 à la tour
1 - Déplacer le disque de haut de la tour 2 à la tour
3 - Déplacer le disque de haut de la tour 1 à la tour
2 - Déplacer le disque de haut de la tour 1 à la tour
3 - Déplacer le disque de haut de la tour 2 à la tour
3
39Voyons cela de plus près
40Pas-à-pas avec n3
n
entier n nfact lire n si (n lt 0) alors écrire
entrée négative n sinon hanoi(n,1,2,3)
entier n
. . .
. . .
41n
3
entier n lire n nfact si (n lt 0) alors écrire
entrée négative n sinon hanoi(n,1,2,3)
lire n
. . .
. . .
42entier n lire n si (n lt 0) alors écrire entrée
négative n sinon
n
entier
4
hanoi(n,1,2,3)
. . .
. . .
43n
3
entier
entier n nfact lire n si (n lt 0) alors écrire
entrée négative n sinon hanoi(3,1,2,3)
3
n
entier
1
entier
2
3
si (n 0) retourner hanoi(2,3,2,1) hanoi( , ,
, )
. . .
. . .
44TITLE hanoi-program SPILE SEGMENT STACK
DW 100 DUP(?) SPILE ENDS SDATA SEGMENT n dw
6 SDATA ENDS SCODE SEGMENT ASSUME
CSSCODE,DSSDATA DEBUT mov ax,sdata mov
ds,ax xor ax,ax xor cx,cx xor dx,dx
xor bx,bx mov ax,n mov cl,1 la tour i
mov ch,2 la tour j mov dh,3 la tour k
call hanoi sortie MOV AX,4C00H INT 21H
45hanoi proc near si1 cmp ax, 0
comparer ax avec 0 ja else
si ngt 0, continuer ret else
dec ax décrémenter ax de
1 c'est-à-dire égal à n-1 mov temp,
ch mov ch, dh mov dh, temp push
cl sauvegarder en premier le i push dh
sauvegarder en deuxième le k push ch
sauvegarder en troisième le j push ax
mettre n -1 sur la pile call hanoi
appel à hanoi
46- passer au déplacement des tours
- mov al, cl mettre le i dans al
- mov ah,2
- int 21h
- mov al, 32 mettre un blanc dans al
- mov ah,2
- int 21h
- mov al, dl mettre le k dans al
- mov ah,2
- int 21h
47 pop ax ax n-1
pop dh pop ch pop cl push ch
push cl push dh call hanoi
ret Hanoi endp SCODE ENDS
END DEBUT