Académique Documents
Professionnel Documents
Culture Documents
>1 de 10
Plan
I - Introduction:
II - La notion de complexité:
1. Définitions:
2. Notation de Landau: ( ), ( ), ( )
3. Classes de complexité usuelles
1. Le coût d'instruction:
a- Instructions élémentaires:
b- Instructions composées:
2. Calcul de la complexité algorithmique - Exemples:
3. Différentes nuances de complexité:
I - Introduction:
Un algorithme est une solution à un problème donné, sa fiabilité repose donc sur 3 critères:
La terminaison: Il doit finir, dans tous les cas, par rendre une solution.
La correction: La solution doit être juste.
L'optimalité
On s'intéresse dans ce chapitre au dernier critère qu'on appellera "la complexité algorithmique" et qui se décompose en
complexité temporelle et complexité spatiale. Le facteur temps est généralement plus important que celui de l'espace. On
focalisera notre étude sur la complexité temporelle.
Exercice:
Soit la suite de Fibonacci définie par la relation récurrente:
1. En se basant sur la relation récurrente, écrire une fonction récursive qui calcule .
2. Ecrire , la version itérative de .
3. En utilisant la bibliothèque et de , comparer graphiquement le temps d'exécution des 2
fonctions, pour dans .
4. Conclure?
Réponses:
1. et 2. les fonctions et :
Chap02 - Complexité algorithmique
1 def fiboRec(n): >2 de 10
2 if n<2:
3 return n
4 return fiboRec(n-1)+fiboRec(n -2)
5
6 def fiboIt(n):
7 if n<2:
8 return n
9 a,b =0,1
10 for i in range(1,n):
11 c=a+b
12 a=b
13 b=c
14 return c
15
3. Test expérimental:
1 import time as tm
2 import matplotlib.pyplot as plt
3
4 x=[i for i in range(10,36)]
5
6 def coutsTemps(f,x):
7 y= []
8 for i in x:
9 t1=tm.time()
10 f(i)
11 t2=tm.time()
12 y.append(t2-t1)
13 return y
14
15 yRec=coutsTemps(fiboRec,x)
16 yIt=coutsTemps(fiboIt,x)
17
1 plt.plot(x,yRec,"-g",label ="Fibo récursive")
2 plt.plot(x,yIt,"-b",label="Fibo itérative")
3 plt.legend(loc="upper left")
4 plt.xlabel("$n$")
5 plt.ylabel("Temps d'exécution")
6
Text(0, 0.5, "Temps d'exécution")
4. Conclusion: l'algorithme de la version récursive roule beaucoup plus lentement dès que dépasse relativement à
celui de la version itérative.
II - La notion de complexité:
1) Définitions:
Définition:
Lacomplexitéd'un problème mathématique est une mesure de la quantité de ressources nécessaires à la
résolution du problème . Cette mesure est basée sur une estimation du nombre d'opérations de base effectuées par
l'algorithme en fonction de de l'algorithme. Pour un même problème , on peut
trouver plusieurs algorithmes ( , , .., ).
L'objectifdelacomplexité
est d'évaluer le coût d'exécution de chaque algorithme afin de choisir le meilleur.
Chap02 - Complexité algorithmique
>3 de 10
Exemple:
Quelle est la taille des données en entrée sur la base de laquelle la complexité de chaque algorithme suivant sera évaluée:
1. Algo1:
Entrée: Liste de floats .
Sortie: Maximum de .
La taille de la liste: .
2. Algo2:
Entrée: Entier .
Sortie: ième terme de la suite de fibonacci.
3. Algo3:
Entrée: Chaîne de caractère .
Sortie: Chaîne de caractère miroir de . Exemple .
La taille de la chaîne: .
4. Algo4:
Entrée: Entier .
Sortie: Nombre de chiffres impairs dans la représentation décimale de .
Définition:
Complexitétemporelle(entemps) est le nombre d'opérations élémentaires (affectations, comparaisons, opérations
arithmétiques) effectuées par un algorithme.
Complexitéspatialeen ( espace)
est le nombre d'emplacements mémoires occupés lors de l'exécution d'un
programme.
Remarque:
On s'intéressera dans ce qui suit, plus, à la complexité temporelle.
2) Notation de Landau: ( ), ( ), ( )
Définitions:
Soit une fonction qui désigne le temps de calcul d'algorithme relativement à , la taille de données mise en jeux.
Exemple:
Prouvons que la fonction est en et elle est en , il nous suffira de trouver une constante
qui établit l'inégalité à partir d'un rang :
Propriétés
Temps constant: on a toujours . (P1)
La réflexivité: on a toujours . (P2)
La transitivité: Si et alors . (P3)
La somme:
Si et , alors . (P4)
Si et , alors . (P5)
Le produit: Si et , alors . (P6)
Constante Le temps d'exécution ne dépend pas des données traitées, ce qui est assez rare !
Linéaire Augmentation linéaire du temps d'exécution quand le paramètre croit (si le paramètre double, le temps double).
Quand le paramètre double, le temps d'exécution est multiplié par . Exemple : algorithmes avec deux boucles
Quadratique
imbriquées.
Ici, est le terme de plus haut degré d'un polynôme en ; il n'est pas rare de voir des complexités en
) Polynômiale
ou .
Exponentielle Quand le paramètre double, le temps d'exécution est élevé à la puissance avec .
Définition:
On appelle instruction de base, ou instruction élémentaire, toute :
1. Affectation.
2. Test de comparaison : , , , , .
3. Opération de lecture ( ) et écriture ( ).
4. Opération arithmétique : , , , , , .
Exemple:
Que vaut le coût de l’algorithme :
1 somme = n + 1 #instr1
2 somme = somme ∗ n #instr2
3 somme = somme/2 #instr3
4
b- Instructions composées:
Définition:
On appelle instruction composée toute instruction contenant:
1 if test: A else B
2
Et on a:
1 for i in range(p,n): Ai
2
Et on a:
1 while t: At
2
Et on a:
4. Autres instructions composées et élémentaires: Le coût est la somme des coûts de ses éléments.
Chap02 - Complexité algorithmique
>6 de 10
Exemple1
La fonction suivante permet de retourner le quotient et le reste de la division entière d'un nombre entier par (non nul).
1 def division(a,b) :
2 q=a//b
3 r=a%b
4 return (q,r)
5
Le nombre d’opérations est quelque soient et . Le nombre d'opérations est constant et le temps de calcul l'est aussi.
Exemple2
La fonction suivante retourne la somme des éléments d'une liste :
1 def somme(L) :
2 s=0
3 n=len(L)
4 for i in range (n) :
5 s=s+L[i]
6 return s
7
Le paramètre de complexité est la taille de la liste d'entrée . On exécute dans le corps de la boucle 3 opérations
(addition, affectation et accés à ) pour itérations. Le nombre total d'opérations est : .
Complexité :
Exemple3:
La fonction suivante permet de remplir une matrice par l'utilisateur:
1 def RemplirMatrice(M) :
2 n=len(M)
3 p=len(M[0])
4 for i in range(n) :
5 for j in range(p) :
6 print("T[",i,"][",j,"]=")
7 T[i][j]=int(input())
8
Le paramètre de complexité est la taille de la matrice d'entrée et le coût pour saisir une valeur est (print, input,
int et affectation). Les deux boucles imbriquées multiplie ce coût par (nombre d'itérations total). Le nombre total
d’opérations est :
Complexité : , si
Exemple4:
La fonction suivante retourne la matrice produit de 2 matrices et sur la base de la formule:
:
Chap02 - Complexité algorithmique
>7 de 10
1 def ProduitMatriciel(A,B) :
2 n=len(A) #nombre de lignes de A
3 m=len(A[0]) #nombre de colonne de A
4 p=len(B[0]) #nombre de colonnes de B
5 C=[p*[0] for i in range(n)]
6 for i in range(0,n) :
7 for j in range (0,p) :
8 s=0
9 for k in range (0,m) :
10 s = s + A[i][k]*B[k][j]
11 C[i][j]=s
12 return C
13
Complexité : , si .
Exemple5:
La fonction suivante effectue une recherche dichotomique de dans un tableau trié de taille :
1 def RechDichotomique(T,x) :
2 g,d=0,len(T)- 1
3 while g<=d :
4 m=(g+d)//2
5 if T[m]==x :
6 return True
7 if T[m]<x :
8 g=m+1
9 else :
10 d=m-1
11 return False
12
Le paramètre de complexité est la taille . Les coût à l'exterieur de la boucle et à son interieur sont constants,
donc le coût total est majoré par où est le nombre de passages maximum dans la boucle .
Ce nombre dépend de la taille de la liste en cours de traitement dans la boucle.
Pour majorer le coût on considère que c.a.d n'est plus vérifiée.
Avant le ième maximum dérnier passage possible ( ), on traite la sous liste de taille atteint au
maximum si .
Donc vérifie: soit: ou encore:
Soit .
Complexité : .
Exemple6:
La fonction suivante effectue une recherche d'un de taille dans un de taille et retourne sa position s'il est
trouvé ou sinon:
1 def searchWord(mot,texte) :
2 m,n=len(mot),len(texte)
3 if m>n:
4 return False
5 for i in range(n-m+1) :
6 j=0
7 while j < m and mot[j] == texte[i + j] :
8 j=j+1
9 if j == len(mot) :
10 return i
11 return False
12
Le nombre d'opérations total est de l'ordre de . En particulier le maximum est atteint pour
Car: pour fixe la fonction trinôme est maximale à
et on obtient le coût maximal: .
Exemple7:
La fonction suivante résout récursivement le problème des "Tours de Hanoï":
Déplacer, un par un, les disques de la tour vers la tour en utilisant la tour et en respectant l'ordre
du plus grand au plus petit (du bas vers le haut) dans chaque tour.
1 def hanoi(n,a=1,b=2,c=3) :
2 if (n > 0) :
3 hanoi(n-1,a,c,b)
4 print("Déplace ",a,"sur",c)
5 hanoi(n-1,b,a,c)
6
Chap02 - Complexité algorithmique
>9 de 10
L'opération élémentaire étant le mouvement d'un plateau, pour déplacer une tour de taille , il faut déplacer deux
tours de taille et un plateau (déplacer une tour vide, c'est ne rien faire). La complexité vérifie donc
ou encore, avec
Donc
Définition
Soit l’ensemble des données de taille fixe d'un algorithme et est le coût de son exécution sur de .
La complexité au pire des cas de l'algorithme, est le plus grand nombre d'opérations qu'il aura à exécuter sur :
, .
La complexité au meilleur de l'algorithme, est le plus petit nombre d'opérations qu'il aura à exécuter .
, .
La complexité en moyenne de l'algorithme, est la moyenne des ses complexités sur :
où est la probabilité d'avoir la donnée en entrée de l'algorithme.
Remarque
Les complexités calculées aux exemples précédents sont aux pires des cas.
Exemple
Ecrivons l'algorithme de la recherche d'un élément dans un tableau de taille et calculons la complexité dans:
Le pire des cas: L'élément recherché est le dernier (dans la case ) ou il est absent.
Exercice:
Calculer la comlexité des fonctions et écrites au 1er exercice.
1 def fiboRec(n):
2 if n<2:
3 return n
4 return fiboRec(n-1)+fiboRec(n-2)
5
6 def fiboIt(n):
7 if n<2:
8 return n
9 a,b=0,1
10 for i in range(1,n):
11 c=a+b
12 a=b
13 b=c
14 return c
15
Réponses:
Soit est le coût cherché.
2. : vérifie