RECURSIVITE Licence Informatique Algorithmique sur les données Françoise Greffier Françoise Greffier -Licence informatique - Besançon Sommaire Introduction et intérêt Pile des contextes (Factorielle) Arbre des appels (tours de Hanoi) Elimination de la récursivité Elimination : premier modèle Elimination : deuxième modèle Elimination : troisième modèle Françoise Greffier -Licence informatique - Besançon LA RECURSIVITE Définition La récursivité est un procédé pour lequel dans une définition apparaît la définition elle même. Quand ? Suite récurrentes (exemple : factorielle) Type récursifs Liste non vide = premier + liste Arbre binaire = racine + sous-arbre droit + sous-arbre gauche Définitions récursives Grammaire : <E> ::= + (<E>,<E>) <E> ::= * (<E>,<E>) <E> := Nombre || identificateur Françoise Greffier -Licence informatique - Besançon FONCTION FACTORIELLE Règle récursive : fact(n) = n * fact (n-1) Condition d’arrêt : fact (0) =1 int fact (int n){ if (n = = 0) return 1; else return (n * fact (n-1)); } Françoise Greffier -Licence informatique - Besançon PILE DES CONTEXTES A chaque appel d’une fonction récursive, les arguments transmis par valeur et les variables locales sont empilés. Ces valeurs constituent le contexte d’activation de l’appel. A chaque retour le contexte situé en haut de la pile est disponible Les contextes sont indépendants Françoise Greffier -Licence informatique - Besançon EXECUTION DE FACTORIELLE(3) N° appel 1 (empiler) 2 (empiler) 3 (empiler) 4 (empiler) N° retour Contexte N=3 N=2 N=1 N=0 (dépiler) => 3 N=1 (dépiler) => 2 N=2 (dépiler) => 1 N=3 (dépiler) Pile Françoise Greffier -Licence vide informatique - Besançon Action N*fact(2) N*fact(1) N*fact(0) Return(1) Return (1*1) Return (2 *1) Return (3 *2) Retour au point appelant ALGORITHME RECURSIF AVANTAGES Fiabilité : Solution naturelle et facile à concevoir : si la fonction est récursive quand la structure de données traitée est récursive Exemples : Traitement sur les arbres Tours de Hanoï Françoise Greffier -Licence informatique - Besançon Les tours de Hanoï Problème Problème : Soit n tours de tailles décroissantes sur un socle A, transférer les n tours sur le socle B en utilisant un socle intermédiaire C. Déplacement d’une tour : on ne peut empiler qu’une tour de plus petite taille sur une autre tour Socle FrançoiseA Greffier -Licence informatique - Besançon Socle B Socle C Paramétrage void Hanoi(int n, socle& A, socle& B, socle&C); n : nombre de tours A : socle de départ (valeur initiale : suite de n tours décroissantes) B : socle de d’arrivée (valeur initiale : vide) C : socle intermédiaire (valeur initiale : vide) Françoise Greffier -Licence informatique - Besançon Les tours de Hanoï : résolution Socle A Socle B Socle C Socle FrançoiseA Greffier -Licence Socle B Socle C informatique - Besançon RESOLUTION RECURSIVE Cas trivial (arrêt) n=1 : il suffit de déplacer l’unique tour de A vers B Règle récursive n>1 : Hanoi (n-1, A ,C, B) Déplacer (A,B) Hanoi (n-1, C, B, A) Françoise Greffier -Licence informatique - Besançon FONCTION HANOI A : départ B : arrivée C: intermédiaire void Hanoi (int n, socle& A, socle& B, socle&C){ if (n = = 1) Déplacer (A,B); else { Hanoi (n-1,A,C,B); Déplacer (A,B); Hanoi (n-1,C,B,A); } } Françoise Greffier -Licence informatique - Besançon ARBRE DES APPELS (n=3) Hanoi (3,A,B,C) Hanoi (2,A,C,B) Hanoi (1,A,B,C) Déplacer (A,B) Déplacer (A,C) Hanoi (2,C,B,A) Hanoi (1,B,C,A) Déplacer (C,A) Déplacer (C,B) Déplacer (A,B) Déplacer (B,C) Déplacer (A,B) Françoise Greffier -Licence informatique - Besançon L’ELIMINATION DE LA RECURSIVITE Pourquoi ? Problème d’encombrement mémoire = > Diminuer la taille de la pile Comment ? Écrire un algorithme itératif équivalent Gérer dans l’algorithme la pile des sauvegardes => ne garder que celles utiles Transformer un algorithme récursif en une version itérative équivalente qui conduise à une diminution de la pile. Françoise Greffier -Licence informatique - Besançon Transformation : un cas simple void fonction (H x){ if (c(x)) A0(x); else { A1(x) ; fonction(F1(x)); } Un seul appel récursif terminal. => La pile est inutile. => Version itérative équivalente qui conduise à l ’élimination de la pile. Françoise Greffier -Licence informatique - Besançon void fonction (H x){ while (! c(x)) { A1(x); x=F1(x); } A0(x); } Transformation : un cas simple c(x) : n <= 0 A0 : cout << "fin"; A1 : cout << n; F1 (x) : n = n - 1; Françoise Greffier -Licence informatique - Besançon void enumerer (int if (n <= 0) cout else { cout << n enumerer n){ << "fin"; ; (n - 1); } void enumerer (int n){ while (n > 0) { cout << n ; n = n - 1; } cout << "fin"; } Transformation : autre modèle T fonction (T2 x) { if (c(x)) return f(x); else { return u (g(x), fonction(h(x))); } T fonction (T2 x){ if (c(x)) return f(x); else {p=g(x); x=h(x); while (! c(x)) { p = u(p,g(x)); x=h(x); } return u (p,f(x)); } } Françoise Greffier -Licence informatique - Besançon Exemple : un seul appel récursif Version récursive : ! c(x) => u [ g(x),fonction(h(x)) ] puis c(h(x)) => u [ g(x),f(h(x)) ] Version itérative : ! c(x) => p=g(x); x=h(x); puis c(h(x)) => u [ g(x),f(h(x)) ] Françoise Greffier -Licence informatique - Besançon même résultat Exemple : deux appels Version récursive ! c(x) => u [ g(x),fonction (h(x)) ] ! c(h(x)) => u [ g(x), u [ g(h(x)),fonction (h2(x)) ] ] c(h2 (x)) => u [ g(x), u [ g(h(x)),f(h2(x)) ] ] Version itérative ! c(x) => p=g(x); x=h(x); même résultat ! c(h(x)) => p = u [ g(x), g(h(x))] x= h2 (x) c(h2 (x)) => u [u [ g(x), g(h(x))] ,f(h2(x)) ] Françoise Greffier -Licence informatique - Besançon u doit être une relation associative Factorielle int fact (int x) { if (x = = 0) return 1; else return (x * fact (x-1)); } c(x) : x = =0 f(x) =1 u:* g(x) : x h(x)=x-1 int fact (int x){ if (x==0) return 1; else {p=x; x=x-1; while (!(x==0)){ p = p * x ; x= x-1; } return p*1; } -Licence} Françoise Greffier informatique - Besançon Transformation : autre modèle algorithme P (T x){ si (c(x)) alors A0(x) sinon { A1(x) P(F1(x)) A2(x) P(F2(x)) . . . Am(x) P(Fm(x)) Am+1(x) } } Françoise Greffier -Licence informatique - Besançon ARBRE DES APPELS (m=2) P(x) A1 P [F1(x)] A1 A2 A3 A2 P [F1(F1(x))] P [F2(F1(x))] A0 On remonte A0 On remonte Françoise Greffier -Licence informatique - Besançon P [F2(x)] A3 On remonte Transformation : autre modèle algorithme P (T x){ SI (numret != 1) alors empiler (x,1) // marque fin de pile Anumret(x) REPETER { empiler (x,numret+1) TANT QUE (non c(x)) FAIRE x <- Fnumret(x) A1(x) FSI empiler (x,2) JUSQU ’A (numret = = 1) x <- F1(x) depiler (x, numret) // fin de FAIT // pile A0(x) depiler (x, numret) TANT QUE(numret = = m+1)FAIRE On empile : Am+1(x) • le contexte (données) depiler (x, numret) • n° de l ’action suivante Françoise Greffier -Licence FAIT informatique - Besançon FONCTION HANOI void Hanoi (int n, socle& A, socle& B, socle&C) { if (n = = 1)Déplacer (A,B); // A0(x) else { // A1(x) : action vide Hanoi (n-1,A,C,B); // P(F1(x)) Déplacer (A,B); // A2(x) Hanoi (n-1,C,B,A);} // P(F2(x)) } c(x) : n = =1 A0(x) : deplacer (A,B) A1(x) : action vide F1(x) : permuter(B,C); n=n-1; A2(x) : deplacer (A,B) F2(x) : permuter(A,C); n=n-1; Françoise Greffier -Licence A3(x) :informatique action vide - Besançon m=2 Am+1 : action vide Dernier appel terminal =>Economie mémoire (pile) Transformation : Hanoi void Hanoi (int n, ...) { SI (numret != 1) alors empiler (x,1) deplacer (A,B); //A2(x) empiler (x,numret+1) REPETER { Pas d ’appel récursif suivant TANT QUE (non c(x)) FAIRE permuter(A,C); n=n-1; //action vide FSI empiler (n,a,b,c,2) JUSQU ’A (numret = = 1) permuter(B,C); n=n-1; depiler (n,a,b,c,numret) FAIT deplacer (A,B); //A0(x) depiler (n,a,b,c,numret) TANT QUE (numret = m+1) FAIRE Am+1(x) Dernier appel est terminal depiler (x, numret) Françoise Greffier -Licence FAIT informatique - Besançon Algorithme à essais successifs AES ou encore algorithme de back tracking idée : construire progressivement une solution à un problème donné en essayant toutes les possibilités à chaque étape de la construction. Rqe : la complexité de ce genre d ’algorithme est de nature exponentielle => à utiliser si l ’on n ’en connaît pas de meilleur. Françoise Greffier -Licence informatique - Besançon Algorithme à essais successifs AES ou encore algorithme de back tracking On part d’une situation initiale So (ex : échiquier vide) pour aller vers une situation finale Sf (ex : Huit reines placées). Plusieurs situations peuvent répondre au problème. La situation finale est atteinte par le passage successif de situations jusqu’à atteindre Sf. Le passage de la situation Si à Si+1 se fait par une action. Pour chaque situation Si on a le choix entre plusieurs actions menant à des situations éventuellement différentes. Françoise Greffier -Licence informatique - Besançon Algorithme à essais successifs MODELISATION Une fonction Succès(S) qui permet de savoir si une situation S répond au problème. Une fonction EnsembleChoix(S) qui permet d ’obtenir à partir d ’une situation S donnée l’ensemble des actions possibles pour passer à une situation suivante. Une fonction Successeur(S,A) qui donne la situation obtenue par l’application de l’action A à la situation S. Pour chaque situation Si on a le choix entre plusieurs actions menant à des situations éventuellement différentes. On appelle chemin une suite d ’actions : <A0, A1, …, An> Françoise Greffier -Licence informatique - Besançon Algorithme Fonction AES (s:Situation) : (Chemin,Situation) Variables trouvé, choix si succès(s) alors trouvé=vrai; retourner(vide,s) sinon trouvé=faux; choix <- ensembleChoix(s) tant que choix n’est pas vide et non trouvé faire action <-un élément de choix choix <-choix - {action} (chemin,situation)<- (AES (successeur(s,action))) fin tant que si trouvé alors ajouter(action, chemin),sf)) sinon retourner (Erreur Chemin, Erreur action); fin si fin si Françoise Greffier -Licence informatique - Besançon