• Aucun résultat trouvé

Une procédure est dite récursive si, et seulement si, elle fait appel à elle-même, soit directement soit indirectement

N/A
N/A
Protected

Academic year: 2022

Partager "Une procédure est dite récursive si, et seulement si, elle fait appel à elle-même, soit directement soit indirectement"

Copied!
47
0
0

Texte intégral

(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

(2)

Djamal Rebaïne 2

(3)

- (vision itérative) Un escalier de hauteur h c’est : une séquence de h marches

- (vision récursive) Un escalier de hauteur h c’est : une marche suivie d’un escalier de hauteur h − 1

Un exemple

(4)

Version itérative :

static void monter_escalier( int h ) {

for (int i = 1; i <= h; i++) monter_marche();

}

Version récursive :

void monter_escalier( int h ) {

if (h > 0)

monter_marche();

monter_escalier ( h-1 );

}

Djamal Rebaïne 4

(5)

Récursivité en action

• Que fait l’appel 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, c’est-à-dire 3

appels à monter marche()

(6)

Djamal Rebaïne 6

Recette de récursivité

• S’assurer 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 .

(7)

Fonctionnement d’une fonction récursive

• Création d’une pile pour la sauvegarde

entre autres des paramètres d’appels de

la procédure et la l’adresse de retour.

(8)

Djamal Rebaïne 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 < 0) alors écrire “entrée négative: ” n

• sinon

• nfact factoriel(n)

• écrire “la factorielle de ” n “est” nfact

• où factoriel satisfait le prototype

(10)

Djamal Rebaïne 10

Fonction factoriel int factoriel(entier n) {

si (n < 1) retourner 1

retourner n * factoriel(n-1)

}

(11)

Comment le faire en assembleur?

On a besoin d’une pile!

• En effet, à chaque appel récursif, la valeur du paramètre n est sauvegardée dans la pile de travail.

• Ce processus d’empilement est répété jusqu’à ce que le paramètre actuel (de l’appel) n atteigne la valeur 0. Cela correspond à la fin de l’exécution de la fonction

appelante.

• Ensuite, commence le dépilement, et l’exécution de la prochaine instruction de la fonction appelante est

entamée. Ce processus de dépilement est répété jusqu’à

ce qu’on atteigne la valeur de départ du paramètre n.

(12)

Djamal Rebaine 12

Cela 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 CS:code, DS:Data, SS:Pile 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

(13)

Factoriel 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

(14)

Djamal Rebaïne 14

Djamal Rebaïne 14

Calcul d’une 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 CS:code, DS:Data, SS:Pile 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

(15)

mov 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)

Djamal Rebaïne 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

(17)

Inversion d’une chaine de caractères

• Donnée: S une chaine de caractères

• Question: Afficher S dans le sens inverse

(18)

Djamal Rebaïne 18

Fonction principale

• ecrire “introdroduire la chaîne: ”

• inverser

(19)

Fonction factoriel Entête:

entier factoriel(entier n) Corps:

lire car;

si car <> `.`

inverser;

afficher car;

(20)

Djamal Rebaïne 20

La fonction inverser fonctionne comme suit:

Tant que le caractère lu n’est pas le point,

continuer la lecture;

Arrivé au point, l’affichage 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 CS:code, DS:Data, SS:Pile 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 Affich chaine

(22)

Djamal Rebaïne 22

inverser Proc near; les appels récursifs sont gérés exclusivement par la pile.

mov ah,1 ; lecture d’un 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 d’un 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

code ends; fin du programme principal end debut

(24)

Djamal Rebaïne 24

• Rechercher l’élément C dans un tableau trié dans l’ordre croissant.

……… …..

milieu

L u

A

C?

(25)

• Int void recherche(C,L,u:entier; trouve:booleen)

• {

• si (u <= L)

• { milieu = (u - L + 1) div 2;

• si A[milieu] = C

• return (milieu);

• sinon si A[milieu] > C

• recherche(C,L,milieu-1);

• sinon recherche(C,milieu+1,u);

• }

• sinon return (-1);

• }

(26)

Djamal Rebaïne 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 CS:code, DS:Data, SS:Pile 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;

mov BX, SI

Add BX, tableau[1] ; adresse du dernier élément du tableau push BX

push SI call dichoto

Fin: mov AX,4c00h int 21h

(27)

Dichoto proc near;

pop SI pop BX CMP SI,BX

JL fin ; continuer jusqu’à il n’y 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 push SI dichoto jmp fin Autreappel: push SI push BX dichoto

(28)

Djamal Rebaïne 28

Les nombres de Fibonacci

Question: Écrire un programme qui calcule le nombre de Fibonacci défini comme suit:

1

; 0

1 n

si ;

1 0

2 1

F F

F F

F n n n

èm

e n

(29)

TITLE fibonacci

SPILE SEGMENT STACK DW 100 DUP(?)

SPILE ENDS SDATA SEGMENT n dw 6

SDATA ENDS SCODE SEGMENT

ASSUME CS:SCODE,DS:SDATA 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 int 21h sortie:

MOV AX,4C00H INT 21H

(30)

Djamal Rebaïne 30 Fibo proc

si1:

cmp ax, 1 ; comparer ax avec 1 ja else ; si n<= 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 SCODE ENDS

END DEBUT

(31)

Les tours de Hanoï

http://www.multimania.com/fmaire/jeux/hanoi/hanoi.html

http://members.aa.net/~wgf/Hanoi/Hanoi.html

(32)

Djamal Rebaïne 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)

Djamal Rebaïne 34

Fonction principale

• entier n

• lire n

• hanoi(n,1,2,3)

• où hanoi satisfait le prototype

hanoi(entier, entier, entier, entier)

(35)

• Supposons qu’on 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 s’aidant de la tour

1.

(36)

Djamal Rebaïne 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 > 0) {

hanoi(n-1, i, k, j)

écrire "Déplacer i vers k);

hanoi(n-1, j, i, k)

}

(37)

• #include <iostream.h>

• void hanoi (int,int,int,int)

• void hanoi(int n,int i,int j,int k)

• {

• if (n>0)

• {

• hanoi(n-1,i,k,j);

• cout <<“déplacer le disque de haut de la tour<<i<<“ à la tour “<<k;

• hanoi(n-1,j,k,i);

• }

• main()

• {

• int n;

• cin>>n;

• hanoi(n,1,2,3);

(38)

Djamal Rebaïne 38

Exemple avec n = 4 disques

On obtient la série d’affichages 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

(39)

Voyons cela de plus près

(40)

Djamal Rebaïne 40

Pas-à-pas avec n=3

entier n nfact lire n

si (n < 0) alors écrire “entrée négative: ” n sinon

hanoi(n,1,2,3);

entier n

. . .

. . .

n

(41)

entier n lire n nfact

si (n < 0) alors écrire “entrée négative: ” n sinon

hanoi(n,1,2,3) lire n

. . .

.

n 3

(42)

Djamal Rebaïne 42

entier n lire n

si (n < 0) alors écrire “entrée négative: ” n sinon

hanoi(n,1,2,3)

. . .

. . .

n 4 entier

(43)

entier n nfact lire n

si (n < 0) alors écrire “entrée négative: ” n sinon

hanoi(3,1,2,3)

1

. . .

. . .

3 2

3 3

n entier

entier n

entier

si (n  0) retourner

hanoi(2,3,2,1)

hanoi( , , , )

(44)

Djamal Rebaïne 44 TITLE hanoi-program

SPILE SEGMENT STACK DW 100 DUP(?)

SPILE ENDS SDATA SEGMENT n dw 6

SDATA ENDS SCODE SEGMENT

ASSUME CS:SCODE,DS:SDATA 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

(45)

hanoi proc near si1:

cmp ax, 0 ; comparer ax avec 0 ja else ; si n> 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

(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

Djamal Rebaïne 46

(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

E

ND DEBUT

Références

Documents relatifs

Il nous faut donc partir de 4 nombres cogéniques ayant le même nombre de chiffres et, pour ce faire, en rechercher tout d'abord car nous n'en avons pas trouvé. Voici une méthode,

Un nombre entier n est dit « puissant » si pour chaque facteur premier p de cet entier, p² est aussi un diviseur de n.. Un nombre d’Achille (1) est un entier puissant sans être

(b) Une famille est g´ en´ eratrice si et seulement si le rang de la matrice est ´ egal au nombre de lignes (ici 3), donc d’apr` es le calcul pr´ ec´ edent la famille n’est

une factorielle plus 1 ou moins 1 et qui est aussi un

Soient p un nombre premier et q un nombre rationnel

Mettre en évidence en basse tension que lorsqu'on augmente le nombre de récepteurs, l'intensité traversant le circuit principal augmente.. Copyright © Cours de Physique et de Chimie

Je cherche le plus grand nombre entier pair s’écrivant avec 4 chiffres différents qui respecte les conditions suivantes : La somme des 4 chiffres est 6... Je cherche le plus

→ En 1949, Erdös montra le joli résultat suivant : pour tout entier k &gt;1 donné, il existe une infinité de nombres 2-pseudo-premiers qui sont chacun produit de k facteurs