La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

INF1101 Algorithmes et structures de données

Présentations similaires


Présentation au sujet: "INF1101 Algorithmes et structures de données"— Transcription de la présentation:

1 INF1101 Algorithmes et structures de données
Cours 5 La récursivité INF1101 Algorithmes et structures de données

2 INF1101 Algorithmes et structures de données
Plan du cours I. Notions de base II. Exemple simple (imp. de nombres) III. Limitations (suite de Fibonacci) Arbres (introduction) Autres exemples VI. Sous-séquence de somme maximale VII. Backtracking INF1101 Algorithmes et structures de données

3 INF1101 Algorithmes et structures de données
I - Notions de base Définition: Un objet est récursif s'il est défini à partir de lui-même. Une fonction est récursive si elle peut s'appeler elle-même de façon directe ou indirecte Idée générale: Pour bien comprendre la notion de récursivité, il faut connaître le concept des piles. Les piles sont des structures qui peuvent contenir plusieurs éléments. Toutefois, seul le dernier élément ajouté à la pile est accessible. Une analogie peut être faite avec les piles d'assiettes. Seule l'assiette du dessus est immédiatement accessible. De la même façon, lorsqu'une assiette est ajoutée, celle-ci est nécessairement déposée sur le dessus de la pile. INF1101 Algorithmes et structures de données

4 INF1101 Algorithmes et structures de données
La pile d’assiette Assiette disponible Lorsqu'une fonction est appelée, ses paramètres formels, l'adresse de retour et les variables locales (automatiques) de la fonction appelée sont déposés sur la pile. Toutes ces données sont retirées de la pile à la fin de l'exécution de la fonction. Conséquemment, lors d'appels récursifs, les variables de la fonction sont empilées en cascade. INF1101 Algorithmes et structures de données

5 INF1101 Algorithmes et structures de données
Récursivité (suite) Idée générale : La réalisation d'une tâche par un algorithme récursif repose sur deux éléments: La résolution partielle du problème d'une façon simple. La réalisation du reste de la tâche étant déléguée aux appels récursifs successifs. La détermination d'une condition d'arrêt qui permet d'arrêter la cascade d'appels récursifs. Résoudre le problème au moment où la condition d'arrêt est détectée correspond en général à résoudre un cas trivial de celui-ci. INF1101 Algorithmes et structures de données

6 Champs d'application des algorithmes récursifs
Structures de données définies récursivement (listes, arbres, graphes, etc.) Équations de récurrence (algébriques, vectorielles, booléennes, formelles, ensemblistes, etc.); Rétroaction ("backtracking"). INF1101 Algorithmes et structures de données

7 Avantages et inconvénients
Formulation compacte, claire et élégante. Maîtrise des problèmes dont la nature même est récursive. Désavantages: Possibilité de grande occupation de la mémoire. Temps d'exécution peut être plus long. Estimation difficile de la profondeur maximale de la récursivité. INF1101 Algorithmes et structures de données

8 Fonction récursive factorielle
Soit la fonction Factorielle, effectuant l’opération n! long Factorielle(long N) { if (N==0) return 1; else return (Factorielle(N-1)*N); } Voir main1.cpp INF1101 Algorithmes et structures de données

9 Exécution de Factorielle
int Reponse = Factorielle (4); Factorielle (1) Factorielle (0) Factorielle (2) Factorielle (3) Factorielle (4) INF1101 Algorithmes et structures de données

10 INF1101 Algorithmes et structures de données
Récursivité (suite) Quatre règles régissent la récursivité: Présence de cas de base pouvant être résolu sans récursivité Toujours progresser vers le cas de base à chaque appel récursif « Ayez la Foi »: avoir confiance que les appels récursifs progressent réellement vers le cas de base. Intérêt composé: Ne jamais dédoubler du travail dans deux appels récursifs différents. INF1101 Algorithmes et structures de données

11 II – Exemple simple : impression de nombres
Idée générale: Fonction qui donne l’impression d’un nombre non-négatif N sous forme décimale. Par exemple pour le nombre 248, il est nécessaire d’imprimer 2, puis 4 et finalement 8. La récursivité offre une méthode efficace et simple de programmer une tel méthode. En utilisant l’opérateur %, le dernier chiffre peut être imprimer, suivi des autres par n/10. INF1101 Algorithmes et structures de données

12 Fonction récursive pour N en forme décimale
void printDecimal( int n ) { if ( n >= 10 ) printDecimal( n/10 ); cout.put( ‘0’ + n%10 ); } INF1101 Algorithmes et structures de données

13 Fonction récursive pour N pour n’importe quelle base
void printInt( int n , int base) { static string DIGIT_TABLE = “ abcdef”; if ( n >= base ) printInt( n/base, base ); cout << DIGIT_TABLE[ n%base ]; } INF1101 Algorithmes et structures de données

14 Exemple simple : impression de nombres
Note : Une erreur se produit lors de l’appel à la fonction récursive lorsque en base 1, puisque les deux paramètres sont identiques. Ceci entraîne une série infinie d’appel à la fonction récursive. En testant et en validant la base avant de faire appel à la fonction récursive, ceci éviterait de faire appel à la fonction récursive en base 1. Le test n’est effectué qu’une seule fois puisque ce test sera valide pour tous les appels subséquents. Ceci permettra ainsi de posséder une fonction plus robuste. INF1101 Algorithmes et structures de données

15 Fonction récursive pour N pour n’importe quelle base
void printIntRec( int n , int base) { static string DIGIT_TABLE = “ abcdef”; if ( n >= base ) printIntRec( n/base, base ); cout << DIGIT_TABLE[ n%base ]; } void printInt(int n, int base) if(base <=1 || base > MAX_BASE) cerr << “Impression impossible en base “ << base <<endl; else if(n < 0) cout << ”-”; n = -n; printIntRec(n,base) INF1101 Algorithmes et structures de données

16 III – Limitations: Fonction récursive Fibonnacci
Soit la fonction Fibo (Fibonacci), effectuant l’opération f(n) = f(n-1) + f(n-2) long fibo (long valeur) { if (valeur <= 1) return valeur; else return(fibo(valeur-1) + fibo(valeur-2)); } // voir main1.cpp INF1101 Algorithmes et structures de données

17 Exécution de Fibonnacci
Soit les appels effecutés pour fibo(4) : fibo(4) fibo(3) fibo(2) fibo(1) fibo(0) fibo(2) fibo(1) fibo(1) fibo(0) INF1101 Algorithmes et structures de données

18 INF1101 Algorithmes et structures de données
Danger de Fibonnacci Note : Cette fonction récursive effectue plusieurs appels au même calcul. Par exemple pour déterminer f(n), on calcule d’abord f(n-1), puis au retour de l’appel, f(n-2) est calculé. Or, dans le calcul de f(n-1), f(n-2) est déjà calculé! Ce problème s’aggrave en descendant l’arborescence, puisque f(n-3) sera appelé à 3 reprises : chaque appel récursif entraînera de plus en plus d’appel redondant. Règle 4: Ne jamais dupliquer le travail par la résolution d’une même instance d’un problème dans plusieurs appels récursifs. INF1101 Algorithmes et structures de données

19 IV – Arbres: introduction
Définition : Un arbre est une structure fondamentale et omniprésente en informatique. La plupart des systèmes d’exploitation organisent leur fichiers dans une structure arborescente. INF1101 Algorithmes et structures de données

20 INF1101 Algorithmes et structures de données
Définitions Arbre : Un arbre est une structure composée de noeuds et d'arêtes pour laquelle il n'existe qu'un seul chemin pour passer d'un noeud à un autre. Racine : Premier noeud d'un arbre (noeud sans père). Feuille : Noeud n'ayant pas de fils. INF1101 Algorithmes et structures de données

21 Représentation d’un arbre
C D E F G INF1101 Algorithmes et structures de données

22 INF1101 Algorithmes et structures de données
V – Autres exemples Exemples démontrant des méthodes qui peuvent être implémentés non récursivement et des avantages de la récursivité. Ex : recherche dichotomique (binaire) Ex : Dessin d’une règle INF1101 Algorithmes et structures de données

23 Recherche binaire (dichotomique)
Idée générale : La recherche d’une valeur particulière dans un tableau ordonné se fait par divisions successives du tableau en deux parties. Le fait que le tableau soit ordonné permet de déterminer rapidement la moitié dans laquelle se trouve l’élément recherché. i = début –1 j = fin +1 Tant que i et j ne se rencontrent pas Trouver le milieu du sous-tableau courant Si la valeur cherchée < tableau [milieu] j = milieu Si la valeur cherchée = tableau [milieu] Retourne milieu Si la valeur cherchée > tableau [milieu] i = milieu Retourne -1 INF1101 Algorithmes et structures de données

24 Recherche dichotomique : Exemple d’exécution
Valeur Cherchée = 17; Début = 0, Fin = 10 j milieu i -1 11 1 2 3 4 5 6 7 8 9 10 -2 11 15 17 20 21 30 39 Valeur cherchée < tableau[milieu] Valeur cherchée = tableau[milieu] Valeur cherchée > tableau[milieu] La valeur cherchée est dans la partie gauche du tableau La valeur cherchée est dans la partie droite du tableau On retourne milieu INF1101 Algorithmes et structures de données

25 Recherche binaire : programmation non-récursive
int RechercheBinaire( int * Tableau, int Debut, int Fin, int ValeurCherchee) { int i = Debut - 1; int j = Fin + 1; while ( i+1 != j) int milieu = (i+j)/2; if ( ValeurCherchee < Tableau[milieu]) j = milieu; if (ValeurCherchee == Tableau[milieu]) return milieu; if (ValeurCherchee > Tableau[milieu]) i = milieu; } return -1; INF1101 Algorithmes et structures de données

26 Fonction récursive pour la recherche binaire
template <class Comparable> int binarySearch(const vector<Comparable>& a, const Comparable& x) { return binarySearch(a, x, 0, a.size()-1); } int binarySearch(const vector<Comparable>& a, const Comparable& x, int low, int high) { if(low > high) return NOT_FOUND; int mid = (low+ high)/2; if( a[mid] < x) return binarySearch(a, x, mid+1, high) else if( x < a[mid]) return binarySearch(a, x, low, mid-1); else return mid; } INF1101 Algorithmes et structures de données

27 VI – Sous-séquence de somme maximale
Définition: La technique de diviser et conquérir (divide-and-conquer) est une méthode de résolution de problèmes basée sur la récursivité: Diviser en plusieurs sous problèmes résolus récursivement. Conquérir, où la solution du problème original est composé de la solution des sous-problèmes. INF1101 Algorithmes et structures de données

28 Sous-séquence de somme maximale
Définition: Étant donnée des entiers (possiblement négatifs) A1, A2,. . . , AN, trouver et identifier la séquence correspondante à la valeur maximale de La somme de la sous-séquence est nulle si tous les entiers sont négatifs. INF1101 Algorithmes et structures de données

29 Sous-séquence de somme maximale
Exemple: Soit les entiers suivants: {4, -3, 5, -2, -1, 2, 6, -2}. On divise cet ensemble en deux: Première moitié Deuxième moitié Valeurs Sommes 4* * 5 Sommes à partir du centre (* indique la somme maximale pour chaque moitié) INF1101 Algorithmes et structures de données

30 Sous-séquence de somme maximale
Cas possible: Cas 1: La séquence est situé dans la première moitié. Cas 2: La séquence est situé dans la deuxième moitié. Cas 3: La séquence commence dans la première moitié et se termine dans la deuxième moitié. INF1101 Algorithmes et structures de données

31 Algorithme de la sous-séquence de somme maximale
Sommaire de l’algorithme: Déterminer récursivement la sous-séquence de somme maximale uniquement dans la première moitié. Déterminer récursivement la sous-séquence de somme maximale uniquement dans la deuxième moitié. Avec deux boucles consécutives, déterminer la sous-séquence de somme maximale qui débute dans la première moitié et qui termine dans la deuxième moitié. Choisir la somme la plus élevée des trois. INF1101 Algorithmes et structures de données

32 Fonction récursive pour la sous-séquence de somme maximale
template<class Comparable> Comparable maxSubSum( const vector<Comparable> & a, int left, int right) { Comparable maxLeftBorderSum = 0, maxRightBorderSum = 0; Comparable leftBorderSum = 0, rightBorderSum = 0; int center = ( left + right ) / 2; if(left == right) return a[left] > 0 ? a[left] : 0; Comparable maxLeftSum = maxSubSum(a,left,center); Comparable maxRightSum = maxSubSum(a,center+1,right); for(int i=center; i>=left ;i--) leftBorderSum += a[i]; if( leftBorderSum > maxLeftBorderSum ) maxLeftBorderSum = leftBorderSum; } . . . INF1101 Algorithmes et structures de données

33 Fonction récursive pour la sous-séquence de somme maximale
for(int j=center+1; j<=right; j++) { rightBorderSum += a[j]; if( rightBorderSum > maxRightBorderSum ) maxRightBorderSum = rightBorderSum; } return max3( maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum ); template <class Comparable> Comparable maxSubsequenceSum( const vector<Comparable> & a) return a.size() > 0 ? maxSubSum( a, 0, a.size() – 1) : 0; INF1101 Algorithmes et structures de données

34 Sous-séquence de somme maximale (Exemple)
3 2 -5 -1 max(0,2,0+1) max(3,2,3+2) 3 2 1 3 2 -5 -1 2 max(0,2,0+2) max(0,0,0+0) 3 2 max(2,0,2+0) 2 3 2 -5 -1 -1 2 2 2 2 -5 -1 -1 2 INF1101 Algorithmes et structures de données dstj

35 Sous-séquence de somme maximale (Exemple)
3 2 -5 -1 max(0,2,0+1) max(3,2,3+2) 3 2 1 3 2 -5 -1 2 max(0,2,0+2) max(0,0,0+0) 3 2 max(2,0,2+0) 2 3 2 -5 -1 -1 2 2 2 2 -5 -1 -1 2 INF1101 Algorithmes et structures de données dstj

36 INF1101 Algorithmes et structures de données
VII – Backtracking Problématique : Pour résoudre certains types de problèmes, il peut être souvent utile de procéder à l'exploration systématique des différentes solutions possibles. Il est donc essentiel de développer des techniques algorithmiques qui permettent une telle exploration. Idée générale pour le calcul du trajet du robot: Il s'agit de concevoir un algorithme qui permet à un robot de trouver un chemin menant à la sortie d'un labyrinthe. Pour ce faire le robot explore systématiquement les quatre directions vers lesquelles il peut se déplacer. De plus, afin d'éviter que le robot ne se retrouve sur des cases déjà explorées chacune de celles-ci seront marquées à mesure qu'elles sont visitées. C'est de façon récursive que les cases faisant partie du chemin seront identifiées. INF1101 Algorithmes et structures de données

37 Algorithme du retour-arrière
INF1101 Algorithmes et structures de données

38 INF1101 Algorithmes et structures de données
Plan du site INF1101 Algorithmes et structures de données

39 Programmation du trajet d’un robot mobile
#define Y 9 /* Les dimensions du labyrinthe */ #define X 7 char laby[X][Y] = { {'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'}, {'X', ' ', ' ', 'X', ' ', ' ', ' ', ' ', 'X'}, {'X', ' ', 'X', 'X', ' ', 'X', 'X', ' ', 'X'}, {'X', ' ', ' ', ' ', ' ', ' ', 'X', 'X', 'X'}, {'X', 'X', 'X', ' ', 'X', ' ', 'X', ' ', 'X'}, {'X', 's', ' ', ' ', ' ', ' ', ' ', ' ', 'X'}, {'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'}}; main() { int i, j; bool Parcours(int x, int y); if (Parcours(1,1)) { // Imprimer le résultat de la recherche for (i = 0; i < X; i++, cout<<endl) for (j = 0; j < Y; j++) cout<<laby[i][j]; } else cout<<"Il n'existe aucun chemin.\n"; } INF1101 Algorithmes et structures de données

40 Programmation du trajet d’un robot mobile (suite)
bool Parcours(int x, int y) { if (laby[x][y] == 's') { /* on a trouvé la sortie */ laby[x][y] = 'S'; return true; } else if (laby[x][y] == ' ') { /* la case est libre */ laby[x][y] = 'o'; /* marquer la case visitée */ if (Parcours(x-1, y)) /* Parcours nord */ return(true); else if (Parcours(x, y+1)) /* Parcours est */ else if (Parcours(x+1, y)) /* Parcours sud */ else if (Parcours(x, y-1)) /* Parcours ouest */ else laby[x][y] = '-'; /* on laisse une marque */ } return false; INF1101 Algorithmes et structures de données

41 Retour en arrière - exercice
1 2 3 4 5 6 7 8 9 A B S C D E F G H I J Quel est le chemin parcouru? Combien de retours en arrière? Utiliser des appels récursifs et l’ordre d’appel suivant: Nord Sud Est Ouest INF1101 Algorithmes et structures de données

42 Retour en arrière - réponse
1 2 3 4 5 6 7 8 9 A B C D E F G H I J o X X o S o o X X o o o X o o o o o o o o o E o o o X o o o o o o o o o o o o INF1101 Algorithmes et structures de données


Télécharger ppt "INF1101 Algorithmes et structures de données"

Présentations similaires


Annonces Google