Vous êtes sur la page 1sur 9

Chapitre 7

Complexité algorithmique
1. Introduction
L’algorithmique est l’étude des algorithmes. Un algorithme est une suite d’instructions qui décrit
comment résoudre un problème donnée en un temps fini.
2. Activité :
Vérifier si un tableau L est trié en ordre strictement croissant.
Raisonnement :
-Un tableau L est trié si tous ses éléments respectent l’ordre croissant. C’est-à-dire Ɐ i [1, taille du
tableau], L[i]<L[i+1]
-On peut aussi traiter ce problème par vérifier s’il y a un contre-exemple. C’est-à-dire s’il  i[1,
taille du tableau], L[i]>L[i+1]
on demande d’écrire une fonction Verification qui permet de vérifier cette propriété.
Fonction verification(L[10],n :entier) :booléen
Début
i1
Tantque (i<n) et (L[i]<L[i+1]) faire
ii+1
fin faire
retourner (i>=n)
fin
La question la plus fréquente que se pose à chaque programmeur est la suivante :
Comment choisir parmi les différentes approches pour résoudre un problème ?
La solution algorithmique doit :
- résoudre correctement et de manière efficace le problème.
- être efficace. L’efficacité est évaluée par :
- assure la rapidité : la solution doit avoir un temps d’exécution acceptable (non lente
- prendre en compte la consommation des ressources (espace mémoire utilisée, espace de
stockage)
NB :
-un programmeur doit savoir résoudre un problème et en plus le résoudre efficacement
-l’efficacité des algorithmes est étudiée par la théorie de la complexité.
Dans ce cours on s’intéresse à l’efficacité en terme de temps d’exécution.
3. Définition
La complexité est une branche de l’informatique théorique. Un algorithme à partir d’une donnée
établit un résultat. La taille de la donnée est mesurée par un entier n.
La théorie de la complexité permet de :
- classer les problèmes selon leur difficulté et efficacité
- comparer les algorithmes résolvant un problème donné afin de faire un choix sans devoir les
implémenter
Un algorithme est dit « optimal » s’il possède une complexité minimale parmi les algorithmes de sa
classe.
4. Evaluation de temps d’exécution d’un algorithme
4.1 l’unité de temps
La durée d’exécution d’un algorithme n’est pas mesurée en heure, minutes et secondes. Ces
mesures ne sont pas pertinentes car le même algorithme sera plus rapide sur une machine plus
puissante.
Pour mesuré l’efficacité d’un algorithme on utilise des unités de temps abstraites et
proportionnelles au nombre d’opérations effectuées.
4.2 Les règles de calcul du temps d’exécution

1
- chaque instruction basique consomme une unité de temps telles que les instructions d’affectation,
de lecture, d’écriture, de comparaison…
- Chaque itération d’une boucle rajoute le nombre d’unités de temps consommées dans cette
boucle.
- Chaque appel de fonction rajoute le nombre d’unités de temps consommées dans cette fonction
- Pour compter le nombre d’opérations effectuées par l’algorithme, on additionne le tout
4.3 Exemples
a) Calculer le temps d’exécution de l’algorithme suivant :
Algorithme addition
Variable
X, y, S : entier
Début
Ecrire (″donner la valeur de x″) 1 écriture
Lire (x) 1 lecture
Ecrire (″donner la valeur de y″) 1 écriture
Lire (y) 1 lecture
sx+y 1 addition et 1 affectation (2 opérations)
ecrire (″la somme est : ″, S) 1 écriture
Fin
Donc, au total cet algorithme consomme 1+1+1+1+2+1=7 opération
b) Donner le temps d’exécution de la fonction suivante :
Fonction factorielle (n :entier) :entier
Variable
Début
p1 1 affectation
i2 1 affectation
Tant que (i<=n) faire 1 comparaison il s’agit d’une boucle qui
pp*i 1mul et 1 affectation doit être exécutée (n-1)
ii+1 fois
fin faire 1 addition et 1 affect
retourner (p)
fin 1 retour du résultat
Sachant que : n !=n*(n-1)*(n-2) …*2*1 avec 0 !=1
La boucle commence à partir de la valeur 2 puisque pour 0 !=1 et 1 !=1
Donc, au total le temps d’exécution de cet algorithme est :
1aff+1aff+ (1comp+1mul+1aff+1add+1aff)*(n-1)+1=5(n-1)+3=5n-2 operations
c) Calculer la complexité algorithmique en terme de temps d’exécution de la fonction
suivante :
Fonction
Verification(L[10],n :entier) :booléen
Début 1 affectation
i1 2 comparaisons le traitement est
Tantque (i<n) et (L[i]<L[i+1]) faire réalisé
ii+1 1 affectation et 1 addition (2) au pire des cas (n-1) fois
fin faire
retourner (i>=n)
fin 1 retour + une comparaison (2 unités de temps)

Donc, au total le temps d’exécution de cet algorithme :1+(2+1+1)*(n-1)+1=4n-2 opérations


Remarque :
 L’unité du temps abstraite dépend de/du:
-nombre d’opérations effectuées (addition, soustraction , mul, div, affectation,…)
2
-La nature des données : on ne sait pas toujours combien de fois exactement on va exécuter une
boucle
-nombre de comparaisons effectuées lors d’un branchement conditionnel.
 Le temps exact dépend de la puissance de la machine.
 La solution de calcul de temps d’exécution d’un algorithme est d’utiliser l’unité du temps
abstraite. On parle alors d’un calcul de la complexité algorithmique
5. Calcul de la complexité algorithmique
5.1 Le principe :
La complexité d’un algorithme est la mesure de nombre d’opérations fondamentales qu’il effectue
sur un ensemble de données bien déterminé. Il existe deux modes de complexité :
-La complexité temporelle est une fonction de n qui mesure le temps de calcul pour une donnée de taille n.
-La complexité en mémoire est une fonction de n qui mesure la place mémoire utilisée pour le calcul sur une
donnée de taille n.
Dans la suite de ce cours nous nous intéressons au calcul de la complexité temporelle.
5.2 Les types de la complexité
Il existe trois types de calcul de complexité :
- Complexité au meilleur des cas : on évalue le nombre d’instructions dans le meilleur des cas
(borne inferieure) ;
- Complexité au pire des cas : on évalue le nombre d’instructions dans le pire des cas (borne
supérieure) ;
- C’esr la moyenne des complexités de l’algorirhme sur des données de taille n
On identifie généralement la complexité d’un algorithme avec son pire cas.
5.3 La performance asymptotique dans les pires des cas
La complexité d’un algorithme est une mesure de sa performance qui s’intéresse à des données de
très grandes tailles car les petites valeurs ne sont pas assez informatives et significatives : on parle
alors d’une performance asymptotique dans les pires des cas.
-Performance asymptotique car on s’intéresse à des données de très grande taille.
-pire des cas : car on s’intéresse à une performance dans des situations dont l’algorithme prend le
plus de temps pour être exécuté. En fait, il faut être sûr que l’algorithme ne prend pas plus de temps
que celui qu’on a estimé.
6. O-notation (Notation de Landau)
6.1 Principe :
La complexité calculée d’un algorithme ne représente pas le temps exacte mais plutôt une
approximation du temps ou encore un ordre de grandeur.
Exemples :
-Si un algorithme réalise 5n-2 opérations, on retient juste que l’ordre de grandeur est n.
-Si un algorithme réalise 5n2+3n+2 opérations, on retient juste que l’ordre de grandeur est n2.
Cet ordre de grandeur ou encore l’annotation asymptotique ou notation de Landau est noté par la
fonction O(.). Cette notation exprime la limite supérieure d’une fonction dans un facteur constant.
Formellement :
 n0  IN,  cR, Ɐ n≥n0, f(n)≤cg(n)

Soit n la taille des données à traiter, on dit qu’une fonction f(n) est en O(g(n)) s’il existe un seuil
n0 à partir duquel la fonction f(.) est toujours dominée par g(.) à une constante multiplicative fixée c
près.
6.2 Exemples
a) Prouver que f(n)=3n+52 est de l’ordre de O(n)
Alors il faut trouver une constante c et un seul n0 / Ɐ n ≥ n0 , f(n)≥cg(n)
On remarque que : 3n+52≤4n c’est-à-dire si n≥ 52 alors on déduit que c=4 et que n0=52
Ou encore on peut dire que 3n+52≤ 5n c’est-à-dire si n≥ 52/2 alors on déduit que c=5 et que
n0=52/2=26
NB :On ne demande pas d’optimiser, il suffit de donner des valeurs qui fonctionnent
3
b) Démontrer que : f1(n)= 3n2+2n+8 est en O(n2)
Il faut chercher une constante c :
3n2+2n+8<=4n2
4n2-3n2-2n+8≥0 cad n2-2n+8 =( n-1) 2+9 ≥0 alors pour n0=1 l’inéquation est vérifiée
Donc il existe une constante c=4 et un n>n0=1 dont f1(n)≤4g(n)

c g(n)

6.3 Comparaison asymptotique


En mathématique : La comparaison asymptotique est une f(n)=O(g(n))
méthode consistant à étudier le comportement d’une
fonction au voisinage d’un point (ou en l’infini), en regard du
comportement d’une autre fonction réputée ”simple” et ”connue”,
souvent choisie sur une échelle de référence.
En informatique n0
Au lieu de mesurer directement le nombre de transitions sur la machine de Turing,
compter le nombre d’opérations élémentaires (affectation, additions, soustractions, comparaisons
logiques, etc.) en fonction de la taille du problème.
6.4 Activité
On demande de calculer la complexité de la séquence d’instructions suivante :
Pour i de 1 à N faire
R[i]0
Fin faire

Le traitement T qui est représenté par la boucle pour avec le compteur i nécessite :
-une initialisation de i à 1,
- n comparaisons de i avec N et
- n addition (+1) et affectation
- n affectations d’un zéro à un élément i (i[1,N]) du tableau R (n éléments).
Alors, T(n)= 3n+1 +n=4n+1, c / T(n) ≤cn. Donc T(n) est de complexité O(n)
7. Les règles générales de calcul de complexité d’un algorithme :
7.1 Règles de simplification de calcul d’un temps d’exécution
On calcule le temps d’exécution puis on fait des simplifications. Les quelques règles suivantes
permettent de simplifier les complexités :
-annuler les constantes additives (exemple f(n)=3n+5 on peut éliminer la constante additive 5)
-omettre les coefficients (exemple : 14n2 devient n2 )
-prendre en considération les termes dominants
Exemples : - na domine nb, si a > b (n2 domine n))
-exponentielle domine un polynôme (exemple : 3n domine n5 et également 2n)
- un polynôme domine un logarithme : n domine (log n).
Exemple
Soit à calculer un temps d’exécution d’un algorithme g(n)= 3n2+10n+10
-Eliminer les constantes additives : g(n)= 3n2+10n
-Annuler les coefficients (comme étant ils sont tous à 1) : g(n)= n2+n
-Retenir le plus haut degré g(n)=n2
On dit alors que cet algorithme possède une complexité g(n)=O(n2)
Détaillons plus
On suppose qu’on dispose d'un algorithme dont le temps d'exécution est décrit par la fonction
T(n) = 3n2+10n+10. L'utilisation des règles de la notation O nous permet de simplifier en :
O(T(n)) = O(3n2 + 10n + 10) = O(3n2) = O(n2)
-Pour n = 10 nous avons :
-Temps d'exécution pour le terme 3n2 : 3(10)2 / 3(10)2+10(10)+10 = 73,2%
4
-Temps d'exécution pour le terme 10n : 10(10) / 3(10)2+10(10)+10 = 24,4%
-Temps d'exécution la constante 10 : 10 / 3(10)2+10(10)+10 = 2,4%
2
En plus, le poids de 3n devient encore plus grand quand n augmente
Tel que le cas où n = 100, le temps d’exécution soit 96,7%. Alors, on peut négliger les quantités
10n et 10. Ceci explique les règles de la notation O.
7.2 Les règles de l’annotation O
La notation O est celle qui est le plus communément utilisée pour expliquer formellement les
performances d'un algorithme. Cette notation exprime la limite supérieure d'une fonction dans un
facteur constant. Les règles de la notation O sont les suivantes :
-Les termes constants : O(c) = O(1)
-Les constantes multiplicatives sont omises :
O(cT ) = cO(T) = O(T)
-L'addition est réalisée en prenant le maximum :
O(T1) + O(T2) = O(T1 + T2) = max(O(T1),O(T2))
-La multiplication reste inchangée mais est parfois réécrite d'une façon plus compacte :
O(T1)*O(T2) = O(T1*T2)
-le cas d’une complexité constante
Les instructions de base (lecture écriture affectation) sont des instructions qui prennent un temps
d’exécution constant.
Exemple un algorithme qui saisit deux valeurs et affiche leur somme. Cet algorithme va contenir
deux lectures, une addition et un affiche (ou une addition, affectation puis affiche). Alors, 4 ou 5
opérations à effectuer. On dit donc que c’est un algorithme de complexité O(5) noté par O(1).
-Le cas d’une suite d’instructions :
Traitement 1 (instructions 1) T1(n) (exemple : remplissage d’un tableau O(T1)=O(n))
Traitement2 (instructions 2) T2(n) (exemple : le tri d’un tableau O(T2)=O(n2)) )
Le traitement réalisé par l’algorithme T(n)=T1(n)+T2(n)
O(T)=O(T1+T2)= max(O(T1),O(T2)) (exemple : max(O(n),O(n2))= O(n2))
-Le cas d’une instruction conditionnelle :
Si (condition) alors O(T1(n))
Traitement1 O(T2(n)) O(T)=O(T1(n))+max(O(T2(n)), O(T3(n)))
Sinon = max(O(T1(n)),O(T2(n)), O(T3(n)))
Traitement2 O(T3(n))
Finsi
-La cas d’une boucle :
On multiplie la complexité du corps de la boucle par le nombre d’itérations. Exemple pour la boucle
tant que, la complexité se calcule comme suit pour n itérations :
Tant que (condition) faire O(T1)
Traitement O(T2) O((T1(n)+T2(n)))
Fin faire
Remarque :
Pour calculer la complexité d’un algorithme il faut :
- calculer la complexité de chaque partie de l’algorithme.
- combiner ces complexités conformément aux règles (présentées ci-dessus)
- effectuer sur le résultat les simplifications possibles (présentées ci-dessus)
7.3 Les classes de complexité
Les algorithmes usuels peuvent être classés en un certain nombre de grandes classes de complexité.
Les complexités les plus utilisées sont :

5
- Constante : O(1) Accéder au premier élément d'un
ensemble de données
- Logarithmique : O(logn) Couper un ensemble de
données en deux parties égales, puis couper ces
moitiés en deux parties égales, etc.
- Linéaire : O(n) Parcourir un ensemble de données
- Quasi-linéaire : O(nlogn) Couper répétitivement
un ensemble de données en deux et combiner les
solutions partielles pour calculer la solution
générale
-Quadratique : O(n2) Parcourir un ensemble de
données en utilisant deux boucles imbriquées
- Polynomiale : O(nP) Parcourir un ensemble de
données en utilisant P boucles imbriquées
- Exponentielle : O(2n) Générer tous les sous-ensembles possibles d'un ensemble de données
7.4 Etude de quelques exemples de classes de complexité
a. La complexité linéaire
On demande de trouver la complexité de la fonction rechercheSeq qui permet la recherche d’une
valeur dans un tableau séquentiellement
Fonction rehercheSeq(T[100],x,n :entier) :booléen
Variable
i:entier
Début
i1 (1 fois)
Tant que (i<=n) et (T[i]<>x) faire
ii+1
fin faire
retourner (i<=n)
fin

Le nombre de comparaisons réalisées dans le meilleur des cas est O(1) et dans les pire des cas
pour un tableau de taille n la complexité de la recherche séquentielle est de l’ordre de O(n).

b. La complexité logarithme est une fonction qui prend comme paramètres :


- une base b
- un nombre réel strictement positif n
et elle retourne la puissance à laquelle il faut élever la base b pour obtenir le nombre n.
Exemple :
log2(8)=3 (comme 8=23)
log2(1024)=10 (comme 1024=210)
log3(27)= 3 (comme 27=33)
log10(1000)= 3(comme 1000=103)
soit l’algorithme de recherche dichotomique suivant :
fonction rech_dichot (T[20] ,x,N:entier) :booléen
Variable
Deb,fin, mil,T[20] ,x,i:entier
Début
deb1
finN
mil(deb+fin) div 2
Tant que (deb<=fin et x<>t[mil] ) faire

6
si (x<t[mil]) alors
finmil-1
sinon
debmil+1
finsi
mil(deb+fin) div 2
fin faire
retourner (t[mil]=x)
fin

Exemple avec n = 8 = 23 alors il y a 3 comparaisons

Le tableau de 8 éléments

Cet algorithme impose dans la démarche de découper à chaque fois le tableau en deux jusqu’à
atteindre un seul élément. Soit un tableau de N éléments avec 2 p-1N2p. Le nombre des étapes
nécessaires sera le nombre entier p qui est immédiatement plus grand que log2(N).
Exemple : pour n=16 on a besoin de 4 quand
Pour n=1000 le nombre d’étapes nécessaires est p tel que 2p-1n2p
On a 29<1000<210 alors le traitement est réalisé p=10 fois.

Exemples :soit la taille N des tableaux suivants :


N=2 , Nombre de découpage à faire 1 fois
N=4 , Nombre de découpage à faire 2 fois
N=8 , Nombre de découpage à faire 3 fois
N=15 , Nombre de découpage à faire 4 fois
N=1000 , Nombre de découpage à faire 10 fois
c. La complexité quadratique
Soit l’agorithme de la procédure tri par insertion suivant :
procédure tri_insertion(E/S T[50] :entier, N :entier)
Variable i,j,x :entier
début
Pour i de 2 à N-1 faire
xt[i]
j i
tant que (j>1) et (t[j-1]>x) faire
t[j] t[j-1]
jj-1
fin faire
t[j] x
fin faire
fin

7
- la taille du tableau à trier est n.
- On a deux boucles imbriquées : La première indique l'élément suivant à insérer dans la partie
triée du tableau. Elle effectuera n - 1 itérations puisque le premier élément est déjà trié. Pour
chaque élément donné par la première boucle, on fait un parcourt dans la partie triée pour
déterminer son emplacement.
- Calcul de la complexité:
® Au meilleur des cas : le cas le plus favorable pour cet algorithme est quand le tableau est
déjà trié (de taille n). uniquement la boucle externe qui va fonctionnée alors (n-1) itérations
donc il s’agit d’une complexité de O(n)
® Au pire des cas : Le cas le plus défavorable pour cet algorithme est quand le tableau est
inversement trié
on fera une itération (1seul décalage) pour le 1er élément, deux itérations (deux décalages)
pour le 2ème et ainsi de suite pour les autres éléments.
Alors 1+2+3+4+…+(n-1)
Il s’agit d’une suite arithmétique de raison 1 de 1er terme 1 et du dernier terme n-1
Nombre de terme (dernier terme +premier terme)/2= ((n-1)-1+1) ((n-1)+1)/2
=n(n-1)/2=1/2(n2-n)
2
Alors la complexité est O(n )

8
9

Vous aimerez peut-être aussi