Chapitre 3 (Analyse d’algorithmes) 4.1 Introduction Le but principal de ce cours est de vous apprendre à concevoir des algorithmes efficaces. Cependant, si vous avez le choix entre plusieurs algorithmes afin de résoudre un problème, vous devez être en mesure de choisir le «plus efficace». Un outil essentiel afin de prendre une telle décision est «l’analyse d’algorithmes». Malheureusement, il n’y a pas de recette miracle afin de procéder à l’analyse d’un algorithme en général. C’est surtout l’intuition, le jugement et l’expérience qui nous guide. Il y a cependant certaines techniques qui nous sont très utiles. Par exemple, il faut savoir comment analyser les appels récursifs, les boucles, les alternatives et autres instructions de contrôle (c’est alors que les concepts mathématiques du chapitre 2 joueront un rôle primordial). Ce chapitre a pour but de présenter quelques techniques généralement utilisées en analyse d’algorithmes. 4.2 Analyse des structures de contrôle. Principe de base La durée prise par l’exécution d’un programme pour traiter un exemplaire donné est la somme des durées des instructions exécutées pour traiter cet exemplaire (certaines instructions sont exécutées plusieurs fois). 4.2.1 Séquence Somme des durées de chaque terme 4.2.2 Alternative Durée du test + MAX(durée d’une branche) 4.2.3 Boucle FOR Somme des durées de chaque tour de boucle (fonction Σ) (exemples en classe) 4.2.4 Appel récursif Obtention d’une équation de récurrence par simple inspection de l’algorithme (exemples en classe) 4.2.5 WHILE, REPEAT….. C’est instructions sont plus difficiles à analyser. On essaie habituellement de trouver une fonction des variables impliquées qui décroît à chaque «tour». Il faut alors prouver que la boucle se termine et calculer ou estimer le nombre de tour effectifs. (exemples en classe) 4.3 Utilisation d’un baromètre Un baromètre est une instruction exécutée au moins aussi souvent que toute autre instruction de l’algorithme. De plus - une constante multiplicative n’influence pas le résultat; - la durée effective de l’instruction n’influence pas le résultat. Le temps pris par l’algorithme est donc dans l’ordre exact du nombre d’exécution de l’instruction baromètre. (exemples en classe) 4.4 Analyse en moyenne Nous avons déjà montré que le tri par insertion prenait un temps quadratique dans le pire cas et un temps linéaire dans le meilleur cas. Il est alors naturel de se poser la question suivante : qu’en est-il en moyenne ? Afin de donner un sens à cette question, il nous faut définir «en moyenne». Afin d’apporter cette précision il est nécessaire de connaître la distribution des instances à l’entrée. Cette connaissance est cruciale pour notre analyse en moyenne. Comme cette distribution exacte est rarement disponible, l’analyse en moyenne se fait habituellement sous l’hypothèse simplificatrice voulant que toutes les entrées de taille donnée sont équiprobables. Pour les problèmes de tri, nous ajoutons habituellement l’hypothèse que les éléments à trier sont tous différents (simplifie grandement l’analyse). Afin d’illustrer ce type d’analyse, analysons le tri insertion en moyenne. (exemples en classe) 4.5 Analyse amortie (Lire Brassard section 4.6.) 4.6 Algorithmes procedure insert(T[1..n]) for i = 2 to n do x = T[i]; j = i – 1 while j > 0 and x < T[j] do T[j + 1] = T[j] j=j-1 T[j+1] = x procedure select(T[1..n]) for i = 1 to n-1 do minj = i minx = T[i] for j = i + 1 to n do if T[j] < minx then minj = j minx = T[j] T[minj] = T[i] T[i] = minx function Fibrec(n) if n < 2 then return n else return Fibrec(n - 1) + Fibrec(n - 2) Tri-Fusion(A,p,r) if p < r then q = ( p + r ) / 2 Tri-Fusion( A, p, q ) Tri-fusion( A, q+1 , r) Fusionner( A, p, q, r ) procedure pigeonhole(T[1..n]) array U[1..10000] for k = 1 to 10000 do U[k] = 0 for i = 1 to n do k = T[i] U[k] = U[k] + 1 i=0 for k = 1 to 10000 do while U[k] ≠ 0 do i=i+1 T[i] = k U[k] = U[k] – 1