10.07.2015 Views

n - UQAC

n - UQAC

n - UQAC

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

Analyse des algorithmes1


Efficacité des algorithmes Objectif (1): concerne le génie logiciel Objectif (2): Algorithmes et structures dedonnées. Lorsque l’objectif (2) est important, commentpeut-on mesurer l’efficacité d’un algorithme?3


Pour comparer des solutions, plusieurspoints peuvent être pris en considération Exactitude des programmes (prouver que le résultat del’implantation est celui escompté) Simplicité des programmes Convergence et stabilité des programmes (que nossolutions convergent vers la solution exacte; que laperturbation des données ne change pas d’une manièredrastique la solution obtenue) Efficacité des programmes (que nos solutions ne soientpas lentes et ne prennent pas d’espace mémoireconsidérable) Le point que nous allons développer dans ce chapitre estcelui de l’efficacité des algorithmes.4


Quelques définitions Définition: Un algorithme est un ensembled’instructions permettant de transformer unensemble de données en un ensemble derésultats, en un nombre fini étapes. Pour atteindre cet objectif, un algorithmeutilise deux ressources d’une machine:• le temps;• l’espacemémoire.5


Quelques définitions Définition 1: la complexité temporelle d’unalgorithme est le temps mis par ce dernierpour transformer les données du problèmeconsidéré en un ensemble de résultats. Définition 2: la complexité spatiale d’unalgorithme est l’espace utilisé par ce dernierpour transformer les données du problèmeconsidéré en un ensemble de résultats.6


Comparaison de solutionsPour comparer des solutions entre-elles, deuxméthodes peuvent être utilisées:• Étude empirique• Analyse mathématiqueCette comparaison se fera, en ce qui nousconcerne, relativement à deux ressources critiques:temps, espace mémoire,...Nous allons nous concentrer principalement surle temps d’exécution7


Facteurs affectant le tempsd’exécution1. machine,2. language,3. programmeur,4. compilateur,5. algorithme et structure de données.Le temps d’exécution dépend de la longueur del’entrée.Ce temps est une fonction T(n) où n est la longueurdes données d’entrée.La longueur des données d’entrée, définissant leproblème considéré, est définie comme étantl’espace qu’elle occupe en mémoire.8


ExemplesExemple 1: x=3; la longueur des données dans ce cas estlimitée à une seule variable.Exemple 2:sum = 0;for (i=0; i


Pire cas, meilleur cas et cas moyenToutes les entrées d’une longueur donnée nenécessitent pas nécessairement le même tempsd’exécution.Exemple:• soit à rechercher un élément donné (C) dans un tableau de nélément triés dans un ordre croissant.Considérons les solutions suivantes:1. Recherche séquentielle.• Commencer au début du tableau et considérerchaque élément jusqu’à ce que l’élément cherchésoit trouvé.2. Recherche dichotomique:• tient compte du fait que les éléments du tableau soient déjàtriés. Information ignorée par l’algorithme de la recherchesequentielle.10


Recherche dichotomiqueint recherche_séquentielle(int *tab, int C){int i;i = 0;while (i


Recherche dichotomiqueint recherche_Dicho(int *tab, int C){int sup, inf, milieu;bool trouve;inf = 0; sup =n-1; trouve = false;while (sup >=inf && !trouve) {milieu = (inf + sup) / 2;if (C == tab[milieu])trouve = true;else if (C < tab[milieu])sup = milieu -1;else inf = milieu + 1;if (!trouve)return(-1);return(milieu)} /* fin de la fonction */12


La méthodeempirique Elle consiste à coder et exécuter deux (ouplus) algorithmes sur une batterie dedonnées générées d’une manière aléatoire; À chaque exécution, le temps d’exécution dechacun des algorithmes est mesuré. Ensuite, une étude statistique est entreprisepour choisir le meilleur d’entre-eux à lalumière des résultats obtenus.13


Ces résultats dépendent :Problèmeme! de la machine utilisée; du jeu d’instructions utilisées de l’habileté du programmeur du jeu de données générées du compilateur choisi de l’environnement dans lequel est exécuté lesdeux algorithmes (partagé ou non) .... etc.14


Méthodemathématiquematique Pour pallier à ces problèmes, une notion de complexitéplus simple mais efficace a été proposée par lesinformaticiens. Ainsi, pour mesurer cette complexité, la méthodemathématique, consiste non pas à la mesurer en unité detemps (par exemple les secondes), mais à faire ledécompte des intructions de base exécutées par ces deuxalgorithmes. Cette manière de procéder est justifiée par le fait que lacomplexité d’un algorithme est en grande partie induitepar l’exécution des instructions qui le composent. Cependant, , pour avoir une idée e plus précisede laperformance d’un dalgorithme, il convient de signalerque la méthodeexpérimentaleet mathématiquematique sonten fait complémentairesmentaires.15


Comment évaluerdifférentessolutions?Décompte des instructions Reconsidérons la solution 1 (recherche séquentielle) etfaisons le décompte des instructions. Limitons-nous auxinstructions suivantes:• Affectation ( notée par e)• Test (noté par t)• Addition (notée par a) Il est clair que ce décompte dépend non seulement de lavaleur C mais aussi de celles des éléments du tableau. Par conséquent, il y a lieu de distinguer trois mesuresde complexité:• dans le meilleur cas• dans le pire cas• dans la cas moyen16


Pire cas, meilleur cas et cas moyen Meilleur cas: notée par tmin(n) repésentant la complexitéde l’algorithme dans le meilleur des cas en fonction duparamètre n (ici le nombre d’éléments dans le tableau). Pire cas: notée par tmax(n) repésentant la complexité del’algorithme dans le pire cas en fonction du paramètre n(ici le nombre d’éléments dans le tableau). Cas Moyen: notée par tmoy(n) repésentant la complexitéde l’algorithme dans le cas moyen en fonction duparamètre n (ici le nombre d’éléments dans le tableau).C’est-à-dire la moyenne de toutes les complexités, t(i),pouvant apparaitre pour tout ensemble de données detaille n (t(i) représente donc la complexité de l’algorithmedans le cas où C se trouve en position i du tableau). Dansle cas où l’on connait la probabilité Pi de réalisation de lavaleur t(i), alors par définition, on a:• tmoy(n) = p1 t(1) + p2 t(2) + p3 t(3) + ... +pn t(n)17


Pire cas, meilleur cas et casmoyen Il est clair que pour certains algorithmes, iln’y a pas lieu de distinguer entre ces troismesures de complexité. Cela n’a pasvraiment de sens.18


Pire cas, meilleur cas et cas moyen(rechercheséquentielle) Meilleur cas :• Le cas favorable se présente quand la valeur Cse trouve au début du tableau• tmin(n) = e + 3t (une seule affectation et 3 test:deux tests dans la boucle et un autre àl’extérieur de la boucle) Pire cas:• Le cas défavorable se présente quand la valeur Cne se trouve pas du tout dans le tableau. Dans cecas, l’algorithme aura à examiner, en vain, tousles éléments.• tmax(n) = 1e + n(2t+1e+ 1a)+ 1t + 1t = (n+1)e + na+ (2n+2)t19


Pire cas, meilleur cas et cas moyen (rechercheséquentielle) Cas moyen: Comme les complexités favorable etdéfavorable sont respectivement (e + 3t) et =(n+1)e + na + (2n+3)t, la compexité dans le casmoyen va se situer entre ces deux valeurs. Soncalcul se fait comme suit:• Pour plus de simplicité, on suppose que C existe dans letableau. On suppose aussi que sa probabilité de présencedans l’une des positions de ce tableau est de 1/n.• Si C est dans la position i du tableau, la complexité t(i)de l’algorithme est: t(i) = (i+1)e + ia + (2i+2)t• Par conséquent, la complexité moyenne de notrealgorithme est : Tmoy(n) = 1/n((i+1)e + ia + (2i+2)t|sommer sur i = 0,...,n-1= (3n +1)e/2 + (n+1)a/2 + n(n+4)t20


Complexité asymptotiqueLe décompte d’instructions peut s’avérer fastidieuxà effectuer si on tient compte d’autres instructionstelles que:accès à un tableau,E/S, opérations logiques,appels de fonctions,.. etc.De plus, même en se limitant à une seuleopération, dans certains cas, ce décompte peutengendrer des expressions que seule uneapproximation peut conduire à une solution.Par ailleurs, même si les opérations élémentairesont des temps d’exécution constants sur unemachine donnée, ils sont différents néanmoinsd’une machine à une autre.21


Complexité asymptotiquePar conséquent: Pour ne retenir que les caractéristiques essentiellesd’une complexité, et rendre ainsi son calcul simple(mais indicatif!), il est légitime d’ignorer touteconstante pouvant apparaître lors du décompte dunombre de fois qu’une instruction est exécutée. Le résultat obtenu à l’aide de ces simplifictionsreprésente ce qu’on appelle la complexitéasymptotique de l’algorithme considéré.22


Complexité asymptotique Ainsi, si :• tmax(n) = (n+1)e + (n-1)a + (2n+1)t, alors on dira que la complexité de cette algorithmeest tout simplement en n. On a éliminé toutconstante, et on a supposé aussi que les opérationsd’affectation, de test et d’addition ont des tempsconstants. La complexité asymptotique d’un algorithme décritle comportement de celui-ci quand la taille n desdonnées du problème traité devient de plus en plusgrande, plutôt qu’une mesure exacte du tempsd’exécution. Une notation mathématique, permettant dereprésenter cette façon de procéder, est décritedans ce qui suit:23


Notation grand-OLa • notation Définition: grand-O Soit T(n) indique une fonction une borne nonsupérieure négative. T(n) surest le dans temps O(f(n)) d’exécution. s’il existedeux constante positives c et n 0 telle que.Exemple: T(n) ≤ cf(n) Si T(n) pour = tout 3n 2 n +2 > n 0 .alors T(n) ∈ O(n 2 ).2• Utilité: Le temps d’exécution estT ( n)∈O(n• Signification: Pour toutes les grandes entréesOn désire le plus de précision possible:(i.e., n≥nBien que T(n) 0 ), on est assuré= 3n 2 que l’algorithme+2 ∈ O(n 3 neprend pas plus de cf(n) étapes. ),on ⇒ Borne préfèresupérieure.O(n 2 ).)24


Notation grand-OLa notation grand-O indique une bornesupérieure sur le temps d’exécution.Dire qu’une fonction T(n) est dans O(g(n))signifie donc que le taux de croissance deT(n) est plus petit ou égal au taux decroissance de g(n).• Exemple: Si T(n) = 3n 2 +2 alors T(n) = O(n 2 ).On désire le plus de précision possible:• Bien que T(n) = 3n 2 +2 = O(n 3 ),• on préfère O(n 2 ).25


Grand-O:ExemplesExemple 1: Initialiser un tableau d’entiers• for (int i=0; i


Grand-O:Exemples Exemple 2: T(n) = c 1n 2 + c 2n .• c 1 n 2 + c 2 n ≤ c 1 n 2 + c 2 n 2 ≤ (c 1 + c 2 )n 2• pour tout n ≥ 0.• T(n) ≤ cn 2 où c = c 1 + c 2 et n 0 = 1.• Donc, T(n) = O(n 2 ).Exemple 3: T(n) = c. On écrit T(n) = O(1).27


Grand-OmegaDéfinition: Soit T(n), une fonction nonnégative. On a T(n) = Ω(g(n)) s’il existe deuxconstantes positives c et n 0telles que T(n) ≥cg(n) for tout n > n 0.Signification: Pour de grandes entrées,l’exécution de l’algorithme nécessite aumoins cg(n) étapes.⇒ Borne inférieure.28


Grand-Omega:Exemple T(n) = c 1 n 2 + c 2 n.• c 1 n 2 + c 2 n ≥ c 1 n 2 pour tout n ≥ 0.• T(n) ≥ cn 2 pour c = c 1 et n 0 = 1.• Ainsi, T(n) = Ω(n 2 ) par définition.Noter que c’est la plus grande borne inférieure quiest recherchée.29


La notation ThetaLorsque le grand-O et le grand-omegad’une fonction coïncident, on utilise alors lanotation grand-theta.Définition: Le temps d’exécution d’unalgorithme est dans Θ(h(n)) s’il est à la foisdans O(h(n)) et dans Ω(h(n)).30


ExempleΘ(n)Θ(n 2 )Θ(n 3 )Θ(2 n )Θ(lg n)O(lg n) ⊂ O(n) ⊂ O(n 2 ) ⊂ O(n 3 ) ⊂ O(2 n )31


Taux de croissance32


Taux de croissance Le taux de croissance d’une fonction n’estpas affecté par :• les facteurs constants• les termes d’ordre plus petit Exemples :• 100n+10 2 est une fonction linéaire• 10 5 n 2 + 10 2 n est une fonction quadratique33


Ordre de complexité O (1) : temps constant O(lg n) : temps logarithmique O(n) : temps linéaire O(n log n) : temps n log n O(n 2 ) : temps quadratique O(n k ) (k > 2) : temps polynomial O(2 n ) : temps exponentiel34


Erreurs fréquentesConfondre le pire cas avec la bornesupérieure.• La borne supérieure réfère au taux decroissance.• Le pire cas réfère à l’entrée produisant le pluslong temps d’exécution parmi toutes lesentrées d’une longueur donnée.“Le meilleur cas pour mon algorithme estn=1 car c’est le plus rapide.” FAUX!• On utilise la notation grand-O parce qu’ons’intéresse au comportement de l’algorithmelorsque n augmente.• Meilleur cas: on considère toutes les entrées delongueur n.35


Résumé de quelques règlesd’utilisation Si f(n) est un polynôme de degrée a, alors f(n)est O(n a ) i.e.• On “oublie” les termes de + petit ordre (exposant)• On “oublie” les termes constants On utilise toujours la + petite classe defonctions• On dit “2n est O(n)” et non “2n est O(n 2 )” On utilise toujours l’expression de la fonctionla + simple d’une classe• On dit “3n+5 est O(n)” et non “3n+5 est O(3n)”36


Règlesde simplification 1Si• f(n) = O(g(n))et• g(n) = O(h(n)),alors• f(n) = O(h(n)).La notation O est transitive37


Règlesde simplification 2Si• f(n) = O(kg(n))• où k > 0, une constantealors• f(n) = O(g(n)).Les constantes sont ignorées38


Règlesde simplification 3Si• f 1 (n) = O(g 1 (n))et• f 2 (n) = O(g 2 (n)),alors• (f 1 + f 2 )(n) = O(max(g 1 (n), g 2 (n)))• (f 1 + f 2 )(n) = O(g 1 (n)+g 2 (n)))39


Règlesde simplification 4Si• f 1 (n) = O(g 1 (n))Et• f 2 (n) = O(g 2 (n))Alors• f 1 (n)f 2 (n) = O(g 1 (n) g 2 (n))40


Règlesde simplification 5 & 6 Si p(n) est un polynôme de degré k alors p(n)∈ O(n k ) log k n ∈ O(n ε ) pour toutes constantes k>0 etε>041


Règlespour dériverla complexitéd’unalgorithme Règle 1: la complexité d’un ensemble d’instructionsest la somme des complexités de chacune d’elles. Règle 2: Les opérations élémentaires telles quel’affectation, test, accès à un tableau, opérationslogiques et arithmétiques, lecture ou écrtiure d’unevariable simple ... etc, sont en O(1) (ou en Θ(1)) Règle 3: Instruction if: maximum entre le blocd’instructions de then et celui de elseswitch: prendre le maximum parmi les complexitésdes blocs d’instructions des différents cas de cetteinstruction.42


Règlespour dériverla complexitéd’unalgorithme Règle 4: Instructions de répétition:• La complexité de la boucle for est calculée par lacomplexité du corps de cette boucle multipliée par lenombre de fois qu’elle est répétée.• En règle générale, pour déterminer la complexitéd’une boucle while, il faudra avant tout déteminer lenombre de fois que cette boucle est répétée, ensuitele multiplier par la complexité du corps de cetteboucle. Règle 5: Procédure et fonction: leur complexité estdéteminée par celui de leur corps. Notons qu’on fait la distinction entre les fonctionsrécursives et celles qui ne le sont pas: Dans le cas de la récursivité, le temps de calcul estexprimé comme une relation de recurrence.43


Règlespour dériverla complexitéd’unalgorithme• Pour les fonctions non récursives, leurcomplexité temporelle se calcule en sachantque l’appel à une fonction prend un tempsconstant en O(1) (ou en Θ(1))44


ExemplesExemple 1: a = b;Temps constant: Θ(1).Exemple 2:somme = 0;for (i=1; i


ExemplesExemple 3:somme = 0;for (j=1; j


ExemplesExample 4:somme = 0;for (i=1; i


ExemplesExemple 5:somme = 0;for (k=1; k


Recherche Dichotomiqueint recherche _Dicho(int *tab, int C){int sup, inf, milieu;bool trouve;inf = 0; sup = n; trouve = false;while (sup >=inf && !trouve) {milieu = (inf + sup) / 2;if (C == tab[milieu])trouve = true;else if (C < tab[milieu])sup = milieu -1;else inf = milieu + 1;if (!trouve)return(0);return(milieu)} /* fin de la fonction */49


Recherche DichotomiqueValeur Cherchée e = 17; Début D= 0, Fin = 10imilieuj-1 110 1 2 3 4 5 6 7 8 9 10-2 5 7 9 11 15 17 20 21 30 39Valeur cherchée e = < > tableau[milieu]La La valeur cherchée e e est On dans retourne la la partie milieugauche droite du tableau50


Recherche DichotomiqueAnalyse: comme nous l’avons déjà mentionnéprécédement, il y a lieu de distinguer entre les troisdifférentes complexités.Meilleur cas: Il n’est pas difficile de voir que le casfavorable se présente quand la valeur recherchée C estau milieu du tableau. Autrement dit, la boucle while nesera itérée qu’une seule fois. Dans ce cas, l’algorithmeaura effectué un nombre constant d’opérations; c’està-direen O(1).51


Recherche Dichotomique Pire cas: Ce cas se présente quand l’élément Cn’existe pas. Dans ce cas, la boucle while seraitérée jusqu’à ce que la variable sup < inf. Leproblème est de savoir combien d’itérations sontnécessaires pour que cette condition soit vérifiée.Pour le savoir, il suffit de constater, qu’aprèschaque itération, l’ensemble de recherche estdivisé par deux. Au départ, cet intervalle est égal àsup (= n-1) – inf (= 0) + 1 = n.52


Recherche DichotomiqueItérationintervalle de recherche0 n1 n/22 n/43 n/8................................................k n/2 k53


Recherche Dichotomique On arrêtera les itérations de la boucle while dès quela condition suivante est vérifiéen/2 k = 1 ⇒ k = O(log n) Autrement dit, la complexité de cet algorithme dansle pire cas est en O(log n).54


Efficacité des algorithmes Définition: Un algorithme est dit efficace si sacomplexité (temporelle) asymptotique est dansO(P(n)) où P(n) est un polynôme et n la taille desdonnées du problème considéré. Définition: On dit qu’un algorithme A estmeilleur qu’un algorithme B si et seulement si:tA( n)= O(tB( n);et tB( n)≠O(tA(n))• avec t A(n) et t B( n ) qui indiquent les complexitésdes algorithmes A et B, respectivement.55


Robustesse de la notation O, ΘAlgorithmesA1A2A3A4A5A6Complexitélog nnn log nn 22 nn!et ΩTaille max.Résolue par lesmachineactuellesT 1T 2T 3T 4T 5T 6Taille max.Résolue par lesmachines 100fois plus rapidesZ 1 = T 1100Z 2 =100 T 2Z 3 = 100 Z 3Z 4 = 10 T 4Z 5 = T 5 +log100Z 6 = T 6 +log 100/ logT6 -156


Remarque Les relations entre les T iet les Z idonnéesdans la table précédente peuvent êtreobtenues en résolvant l’équation suivante: 100 f(T i) = f(Z i) Où f(.) représente la complexité del’algorithme considéré.57


Remarque• Pour l’algorithme A6 (n!), nous avons àrésoudre l’équation suivante:100 (T6)! = (Z6)!Pour les grandes valeurs de n, nous avonsla formule suivante (de Stirling)n!=⎛⎜⎝ne⎟⎠⎞n58


Remarque• Par conséquent, on obtient ce qui suit:100⎛⎜⎝T 6e⎞⎟⎠T6=⎛⎜⎝Z 6e⎞⎟⎠Z 6• En introduisant la fonction log, on obtient:log 100 + T 6( log T 6 − 1) = Z 6( log Z 6 − 1)• En posant Z6 = T6 + ε, en approximant log (T6+ε) par log T6, pour de très petites valeurs de ε, onobtient:Z 6=T6+log 100log T 6 −159


Comparaison de fonctions• En comparant deux fonctions f et g, entermes d’ordre, il est souvent préférabled’utiliser cette autre définition de lanotation O.• PosonsL =n→∞limf ( n)g ( n )60


Comparaison de fonctions1. Si L = constante ≠ 0, alors f et g sont demême ordre, c’est-à-dire que f(n) = O(g(n))et g(n) = O(f(n)) ou tout simplementO(f(n)) = O(g(n)).2. Si L = 0 alors f est de l’ordre de g, c’est-àdiref(n) = O(g(n)).3. Si L = ∞ alors g est de l’ordre de f,c’est-à-dire g(n) = O(f(n)).61


Comparaison de fonctions• Remarque: dans plusieurs cas, pour faciliter lescalculs, la règle suivante de l’Hôpital est souventutilisée. Cette règle est pratique car, en général, ladérivée d’une fonction est facile à évaluer que lafonction elle-même:f ( n)limn→∞g(n)f= limn→∞g''( n)( n)• Lire: limite quand n tend vers l’infini, le rapportdes deux fonction est égal au rapport des leurpremière dérivée62


Analyse d’algorithmesnonrécursifs: quelquesexemples63


Produit de deux matricesProduit de deux matrices A(n,p) et B(p,m); on obtientl’algorithme suivant:void multiplier(int *A[][p], int *B[][m], int *C[][m],int n, int m, int p){for (i = 0; i


Produit de deux matrices Analyse: le corps de la boucle sur k est en O(1) carne contenant qu’un nombre constant d’opérationsélémentaires. Comme cette boucle est itérée p fois,sa complexité est alors en O(p). La boucle sur j estitérée m fois. Sa complexité est donc en m.O(p) =O(mp). La boucle sur i est répétée n fois. Prconséquent, la complexité de tout l’algorithme esten O(nmp). Noter que dans ce cas, il n’y pas lieu de distinguerles différentes complexités. Dans tous les cas, nousauronsàeffectuercenombred’opérations.65


Impression des chiffrescomposant un nombre Le problème consiste à déterminer les chiffrescomposant un nombre donné. Par exemple, lenombre 123 est composé des chiffres 1, 2 et 3. Pour les trouver, on procède par des divisionssuccessives par 10. A chaque fois, le reste de ladivision génère un chiffre. Ce processus est répététant que le quotient de la division courante estdifférent de zéro.66


Impression des chiffrescomposant un nombre Par exemple, pour 123, on le divise par 10,on obtient le quotient de 12 et un reste de 3(premier chiffre trouvé); ensuite, on divise12 par 10, et on obtient un reste de 2(deuxième chiffre trouvé) et un quotient de1. Ensuite, on divise 1 par 10; on obtient unreste de 1 (troisième chiffre trouvé) et unquotient de zéro. Et on arrête là ceprocessus.67


Impression des chiffrescomposant un nombrevoid divisionchiffre(int n){int quotient, reste;quotient = n / 10;while (quotient >= 10){reste = n % 10;cout


Impression des chiffrescomposant un nombre Analyse: Comme le corps de la boucle ne contient qu’unnombre constant d’instructions élémentaires, sa complexitéest en O(1). Le problème consiste à trouver combien de foisla boucle while est répétée. Une fois cette informationconnue, la complexité de tout l’algorithme est facile àdériver. Déterminons donc ce nombre. Soit k l’itération k.Nous avons ce qui suit:• itération k 1 2 3 ...... k• valeur de n n/100 n/100^2 ……. n/10^k Donc, à l’itération k, la valeur courante de n est de n/10à lapuissance k69


Impression des chiffrescomposant un nombre Or, d’après l’algorithme, ce processus va s’arrêter dèsquen/10 puissance k < 10 Autrement dit, dès quen < 10 à la puissance (k+1) En passant par le log,k + 1> log n Autrement dit, le nombre d’itérations effectuées estk = O(log n) Par conséquent, la complexité de l’algorithme ci-dessusest en O(log n).70


PGCD de deux nombresint PGCD(int A, int B){int reste;reste = A % B;while (reste !== 0){A = B;B = reste;reste = A % B;}retunr(B);} /* fin de la fonction */71


PGCD de deux nombres Analyse: Encore une fois, le gros problème consiste àdéterminer le nombre de fois que la boucle while estrépétée. Il est clair que dans ce cas, il y a lieu normalementde distinguer les trois complexités. En ce qui nous concerne,nous allons nous limiter à celle du pire cas. Pour ce qui estde celle du meilleur cas, elle est facile à déterminer; mais,en revanche, celle du cas moyen, elle est plus compliquée etnécessite beaucoup d’outils mathématique qui sont endehors de ce cours. Pour ce faire, procédons comme suit pour la complexité dansle pire cas:72


Analyse PGCD suiteAvant tout, nous avons besoin du résultat suivant:Proposition : Si reste = n % m alors reste < n/2Preuve: Par définition, nous avons:Donc reste = n –q.m; q >=1reste


PGCD Suite Durant les itérations de la boucle while,l’algorithme génère, à travers la variable reste,la suite de nombre de nombre {r0, r1, r2, r3 , ...}, représentant les valeurs que prennent lesvariable n et m, oùr = n ; r = m ;r0j1+ 1= rj − 1mod rj; j≥2 De la proposition précédente, on peut déduirer r / 2j + 1=j − 1 Par induction sur j, on obtient l’une des deuxrelation suivantes, selon la parité de l’indice j:74


PGCD suite rj< r0 / 2 j/2 si j est pair rj< r0 / (2 (j-1)/2 si j est impair Dans les deux cas, la relation suivante est vérifiée:• rj < max(n,m) / (2 j/2 ))Dès que rj < 1, la boucle while se termine, c’est-à-dire dèsque:• 2 j/2 = max(n,m) +1 Par conséquent, le nombre de fois que la boucle while estrépétée est égal à• 2log(max(n,m)+1) = O(log max(n,m)). Comme le corps de cette boucle est en O(1), alors lacomplexité de tout l’algorithme est aussi en• O(log max(n,m))75


2. Analyse d’algorithmesrécursifsquelques exemples76


Fonction récursive Définition: une fonction est récursive si ellefait appel à elle-même d’une manière directeou indirecte. La récursivité est une technique deprogrammation très utile qui permet de trouverdes solutions d’une grande élégance à uncertain nombre de problèmes. Attention,,lorsqu’elle mal utilisée, cette subtilitéinformatique peut créer un code totalementinefficace.


Analyse d’algorithmesrécursifsL’analyse de la complexité d’un algorithmerécursif dépend de sa relation de récurrence.Généralement, la meilleure technique consisteà utiliser T(n) comme nombre d’étapesnécessaires à l’application d’un algorithmepour un problème de taille n. La partierécursive de l’agorithmese traduit en relation de récurrence sur T(n).Sa solution est ensuite la fonction de lacomplexité de l’algorithme.78


ExempleLe programme calculant la factoriel d’un entier n#include int factoriel (int);int main() {int n,nfact;cin >> n;if (n < 0)cout


Propriétés d’unerécursion1. La récursion (appels de la fonction à elle-même) doits’arrêter à un moment donné (test d’arrêt).Autrement, l’exécution va continuer indéfinementvoid exemple(){cout


2. Un processus de réduction où à chaque appelde lui-même, il se rapproche de condition d’arrêt.Exemple:int mystere (int n, int y){if (n == 0) return y;else return (mystere (n +1,y));}Pour n > 0, la condition d’arrêt ne pourra pas êtreatteinte.


Pour trouver une solution à un problème d’une manièrerécursive, on cherche à le décomposer en plusieurs sousproblèmesde même nature mais de taille inférieure.La méthode générale étant la suivante :- 1. On détermine les éléments dont dépend la solution etqui caractérisent la taille du problème.- 2. Recherche d’un cas trivial (point d’arrêt) de sa solution- 3. Décomposition du cas général en cas plus simples, euxmêmes décomposables pour aboutir au cas trivial.


Analyse de la fonction factorielle Pour déterminer la complexité de cette fonction, nousallons déteminer combien de fois elle fait appel à ellemême.Unefoiscenombreconnu, ilestalorsfacile dedéterminer sa complexité. En effet, dans le corps decette fonction, il a y a:long factoriel(int n){if (n < 2) return 1return n * factoriel(n-1)}• Un test• Un appel à elle même• Une soustraction et une multiplication• Une opération de sortieEn tout, pour chaque exécution de cette fonction, il y a5 opérations élémentaires qui sont exécutées pour n >2.


Analyse de la fonctionfactorielle Soit t(n) la complexité de la fonction factoriel (n). Iln’est pas difficile de voir, , t(n-1) va représenter lacomplexité de factoriel(n-1). De plus, T(n) et T(n-1)sont reliées par l’expression suivante•T(n) = T(n-1) + 5; si n >2•T(n) = ?? Sinon Cette équation est connue sous le nom d’équation derécurrence. Pour connaître T(n), il y a lieu de passer à larésolution come suit:


Analyse de la fonctionT(n) = T(n-1) + 5T(n-1) = T(n-2) + 5T(n-2) = T(n-3) + 5……………………..……………………..T(2) = T(1) + 5factorielleEn additionnant membre à membre, on arriveà: T(n) = T(1) + 5(n-1) = O(n)


Les tours de Hanoï86


Les tours de Hanoï• Il s'agit d'écrire une fonction qui prend enargument un nombre n d'étages, un piquet dedépart A, un piquet de destination B et unpiquet transitoire C, et qui affiche à l'écranles mouvements à effectuer pour faire passerles n étages supérieurs du piquet A vers lepiquet B en s'aidant du piquet C.87


Les tours de HanoïL'idée de l'algorithme est la suivante :•Si n est nul (condition d'arrêt), il n'y a rien àfaire.•Si n n'est pas nul, on déplace récursivement n-1étages du piquet A au piquet C en s'aidant dupiquet B.• Puis on affiche le déplacement d'un étage dupiquet A au piquet B.• Enfin on déplace récursivement n-1 étages dupiquet C au piquet B en s'aidant du piquet A.88


Les tours de Hanoïvoid hanoi(int n, int i, int j, int k){/*Affiche les messages pour déplacer n disquesde la tige i vers la tige k en utilisant la tige j */if (n > 0){hanoi(n-1, i, k, j)cout


Les tours de HanoïExemple d'exécution du programme pour n = 3:1 -> 21 -> 32 -> 31 -> 23 -> 13 -> 21 -> 290


Analyse de HanoiPour déterminer la complexité de cette fonction, nousallons déteminer combien de fois elle fait appel à ellemême.Une fois ce nombre connu, il est alors facile dedéterminer sa complexité. En effet, dans le corps decette fonction, il a y a:• Un test• Deux appels à elle même• Deux soustractions• Une opération de sortieEn tout, pour chaque exécution de cette fonction, il y a6 opérations élémentaires qui sont exécutées pour n >0.91


Hanoi suite Soit t(n) la complexité de la fonction hanoi(n,i,j,k). Il n’estpas difficile de voir, quelque que soit les trois derniersparamètres, t(n-1) va représenter la complexité de hanoi(n-1, -,-,-). Par ailleurs, la relation entre t(n) et t(n-1) est comme suit:• t(n) = t(n-1)+ t(n-1) + 6, si n > 0• t(0) = 1 (un seul test) Autrement écrit, nous avons:• t(n) = 2 t(n-1) + 6, si n > 0• t(0) = 1 (un seul test)92


Hanoi suite Pour résoudre cette équation (de recurrence), on procèdecomme suit:• t(n) = 2 t(n-1) + 6• 2 t(n-1) = 4 t(n-2) + 2.6• 4t(n-2) = 8 t(n-3) + 4.6• ...................................• ...................................• 2 n-1 t(1) = 2 n t(0) + 6.2 n-1 En additionnant membre à membre, on obtient:• t(n) = 2 n t(0) +6(1+2+4+...... 2 n-1)• = 2 n + 6. 2 n• = O(2 n ).93


Les Nombres de Fibonaccième• Écrire un programme qui calcule le nnombre de Fibonacci défini comme suit:FnFF= +n −1n −2;sin>1F0=0;F1=194


Les Nombres de Fibonacciint fibo(int n){int temp;if (n==0)temp = 0;else if (n==1)temp = 1;else temp = fibo(n-1) + fibo(n-2);return (temp);}95


Les Nombres de FibonacciExemple d'exécution du programme pour n = 10:fibo(0) = 0fibo(1) = 1fibo(2) = 1fibo(3) = 2fibo(4) = 3fibo(5) = 5fibo(6) = 8fibo(7) = 13fibo(8) = 21fibo(9) = 34fibo(10) = 5596


Les Nombres de Fibonacci Soit t(n) la complexité de la fonction Fibonacci(n). Il n’estpas difficile de voir que t(n-1) va représenter la complexitéde Fibonacci(n-1) et t(n-2) celle de Fibonacci(n-2). Par ailleurs, la relation entre t(n), t(n-1) et t(n-2) estcomme suit:• t(n) = t(n-1)+ t(n-2) + 8, si n > 1• t(0) = 1 (un seul test)• t(1) = 2 (2 tests) Pour résoudre cette équation (aux différences), on vaprocéder comme suit:97


Les Nombres de FibonacciSoit G(x) = Sum_{n=0}^{infini} t(n)x^nIl est facile de voir:Sum_{n>1} t(n)x^n = sum_{n>1} t(n-1)x^n + sum_{n>1}t(n-2)x^nPour faire ressortir G(x), on fait comme suit:Sum_{n>1} t(n)x^n = sum_{n=0}^{infini} t(n)x^n - t(0)x^0– t(1)x^1= G(x) – t(1) –t(0)Sum_{n>1} t(n-1)x^n = x sum_{n>1}^{infini} t(n-1)x^(n-1)= x sum_{n>0}^{infini} t(n)x^(n)= x sum_{n=0}^{infini} t(n)x^n –t(0)x^0= x(G(x) – t(0))98


Les Nombres de FibonacciSum_{n>1} t(n-2)x^n = x^2 sum_{n>1}^{infini} t(n-1)x^(n-2)= x^2G(x)Par conséquent, on obtient:= x^2 sum_{n=0}^{infini} t(n)x^(n)G(x) – t(1) – t(0) = xG(x) – x – x^2G(x)G(x)(x^2 – x -1) = x – 3G(x) = (x-3)/(x^2 – x -1) = (x-3)/(x-a)(x-b)Où a = (1+racine(5))/2b = (1-racine(5))/299


Les Nombres de FibonacciOn peut aussi mettreG(x) = 1(x-a) + 1/(x-b)On obtienta = (1/(racine(5))b = -(1/(racine(5))G(x) = 1/(racine(5)(1/(x-a) – 1/(x-b)100


Les Nombres de FibonacciRappels de mathématiques:1/(x-a) = sum_{n=0}^{infini} (a^nx^n)et1/(x-b) = sum_{n=0}^{infini} (b^nx^n);Par conséquent:1/(x-a) - 1/(x-b) = sum_{n=0}^{infini} (a^n-b^n)x^n)101


Les Nombres de FibonacciPar conséquent, on obtient:G(x)= 1/(racine(5))(sum_{n=0}^{infini} (a^n-b^n)x^n)(rel1)Et nous avons aussi:G(x) = Sum_{n=0}^{infini} t(n)x^n (rel2)Par identification entre (rel1) et (rel2), on obtient:t(n) = 1/(racine(5)(a^n –b^n)= O(a^n) = O(((1+racine(5))/2)^n)102


Quelques Références1. Rebaine, D. (2000): une introduction à l’analyse desalgorithmes, ENAG, Alger.2. Notes de cours F. Lemieux3. C. Shaffer (2001): a practical introduction to datastructures and algorithms analysis, Prentice hall.4. G. Brassard, P. Brateley (1996): Fundamentals ofalgorithms, Prentice Hall.5. T.H. Cormen et al. (1990) Algorithms, McGraw Hill.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!