Complexité
Complexité
Complexité
COMPLEXITE ALGORITHMIQUE
1. INTRODUCTION
Exercice
Ecrire en python une fonction qui prend en argument une chaîne de caractères et détermine si le caractère 'a' est
présent dans la chaîne (on retourne soit True soit False).
● Quelques questions:
Problème:
Comment évaluer le coût d'exécution d'un algorithme donné?
La notation O(f (n)) est aussi appelée Notation de Landau : (Complexité asymptotique) (i.e.quand n → ∞)
Exemples
Exemple1:
Prouvons que la fonction T(n)=3n +6 est en O(n) (on écrit aussi 3n +6 ∈ O(n))
But: trouver une constante c ∈ ℝ et un seuil n0 ∈𝑁*, à partir du quel T(n) <c.n
On remarque 3n+6<9n si n>2
3*2+6 <9*2
3*3+6 <9*3
3*4+6 <9*4 On déduit donc que c=9 fonctionne à partir d’un seuil n0=2
3*5+6 <9*5
.
.
.
Remarque:
On ne demande pas d'optimisation (le plus petit c ou n0 qui fonctionne), juste de donner des valeurs qui
fonctionnent;
c =10 et n0 =5 est donc aussi acceptable;
3*5+6 <10*2
3*6+6 <10*3
3*7+6 <10*4
Exemple2:
5. PROPRIÉTÉS DE LA NOTATION O :
✔ Si f(x) = an.xn + an−1.xn−1 + ⋯ + a1.x + a0 (où les ai sont tous des réels),
Alors f(x) ∈ O(xn) (P9)
Note :
Quand f(x) ∈ O(g(x)) et g(x) ∈ O(f(x)), on dit que f(x) et g(x) sont du même ordre (de la même
classe) et on écrit : f(x) ∈ θ(g(x))
O(1) Constante Le temps d'exécution ne dépend pas des données traitées, ce qui est assez rare!
O(log(n)) Logarithmique augmentation très faible du temps d'exécution quand le paramètre croit.
= 1+n+2n+2n
= 1+5n
d. La notation O : motivation
● Les calculs à effectuer pour évaluer le temps d'exécution d'un algorithme peuvent parfois être longs et
pénibles;
● De plus, le degré de précision qu'ils requièrent est souvent inutile;
● On aura donc recours à une approximation de ce temps de calcul, représenté par la notation O(.);
1. qu'une affectation requière 2 ou 4 unités de temps ne change donc pas grand-chose ; d'où le
remplacement des constantes par des 1 pour les multiplications.
2. un nombre constant d'instructions est donc aussi négligeable par rapport à la croissance de la taille des
données ; d'où l'annulation des constantes additives.
3. pour de grandes valeurs de n, le terme de plus haut degré l'emportera ; d'où l'annulation des termes
inférieurs
● On préfère donc avoir une idée du temps d'exécution de l'algorithme plutôt qu'une expression plus précise
mais inutilement compliquée;
Exemple 1 Exemple 2
● La fonction suivante permet de retourner le La fonction suivante permet de retourner la somme des
quotient et le reste de la division d’un nombre éléments d’une liste:
entier a par b.
def Somme(L):
def division (a ,b): s=0
q=a//b for i in rang(len(L)) :
r=a%b s=s+L[i]
return(q,r) return s
● Exemple Exemple
>>> x , y = 10 , 3 >>> L =[1, 2, 8, 4]
>>> division(x , y) >>>Somme(L)
3 , 1 15
● Le nombre d'opérationsest:5 ● Le paramètre de complexité est la taille de laliste
● Temps de calcul est constant d'entrée L.
● Complexité: O(1) ● en fixant i on exécute 2 opérations: (addition et
affectation)
● Nombre de fois d'exécution de ces 2 opérations
est: len(T)
● Len ombre total d'opérations est : 4 * len(L) + 3
● Complexité: O(len(L))= O(n)
def prodMatrice(A,B):
n=len(A) #nombre de lignes de A
m=len(A[0]) #nombre de colonne de A
p=len(B[0]) #nombre de colonnes de B
C=[p*[0] for i in range(n)]
for i in range(0,n):
for j in range (0,p):
s=0;
for k in range (0,m):
s = s + A[i][k]*B[k][j]
C[i][j]=s
return C
● On suppose que A et B sont deux matrices carrées d'ordre n = m = p
● Coût pour calculer une valeur de s est : 3 (produit, addition et affectation)
● Le nombre d'itérations de la boucle sur k pour j fixé égal à m = n
● Le nombre d'itérations de la boucle sur j pour i fixé égal à p = n
● Le nombre total d'opérations est : T(n)=4+ n + n(n(2+n(3))
● Complexité: O(n3)
● L'évaluation de la complexité de cet algorithme est assez simple. Nous allons chercher à savoir combien de
déplacements de disques sont nécessaires pour arriver à nos fins. Très simplement, la fonction calculant ceci
peut être définie de la manière suivante (on peut se baser sur la fonction ci-dessus) :
● T(0) = 0; T(1) = 1; T(n) = 2*T(n-1)+1. On peut démontrer par récurrence que ceci est égal à T(n) = 2n-1 :
● On a T(n+1) = 2*T(n)+1. En supposant que T(n) = 2n-1, on a T(n+1) = 2*(2n-1)+1. On développe ensuite en
T(n+1) = 2*2n -2+1 ce qui nous donne au final T(n+1) = 2n+1-1. On a ainsi démontré que si c'est vrai pour n,
alors c'est vrai pour (n+1). Comme on a T(1) = 2*0+1 = 21-1 = 1, c'est vrai pour tous les n supérieurs à 1. La
complexité exacte de l'algorithme présenté ci-dessus est donc en 2n-1 pour n disques à déplacer de la tour
● On trouve T(n)=2n - 1
● Donc lacomplexité est éxponentielle O(2n)
❖ C(n) = C(n-1) + b
● solution : C(n) = c(0) + b*n = O(n)
● exemples : factorielle, recherche séquentielle récursive dans un tableau
❖ C(n) = a*C(n-1) + b, a ≠ 1
● solution : C(n) = an*(C(0) – b/(1-a)) + b/(1-a) = O(an)
● exemples : répétition a fois d'un traitement sur le résultat de l'appel récursif
❖ C(n) = C(n/2) + b
● solution : C(n) = C(1) + b*log2(n) = O(log(n))
● exemples : élimination de la moitié des éléments en temps constant avant l'appel récursif, recherche
dichotomique récursive
❖ C(n) = a*C(n/2) + b, a ≠ 1
● solution : C(n) = nlog2(a) *(c(1) – b/(1-a)) + b/(1-a) = O(nlog2(a))
● exemples : répétition a fois d'un traitement sur le résultat de l'appel récursif dichotomique
❖ C(n) = C(n/2) + n
● solution : C(n) = O(n)
● exemples : traitement linéaire avant l'appel récursif dichotomique