Vous êtes sur la page 1sur 10

Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données

Module Algorithmique et structures de données



Rappel :


Introduction :
On appel un algorithme la démarche qui permet de résoudre un problème donné, c’est-à-dire d’obtenir un résultat certain en
suivant les étapes (opérations) indiquées dans la séquence d’énoncés ou d’instructions définissant cette démarche.

Un programme est la description (traduction) d’un algorithme dans un langage de programmation.

1. Structure d’un algorithme :


__________________________________________
Algorithme NomDeLAlgorithme ;
__________________________________________
Const c1= ... c2=... ;
Var var1 : Type ; var2 : Type2 ;
__________________________________________
Procedure P1(....)
___________________________________
Debut
.........
fin
___________________________________
fonction F1(....) : Type ;
___________________________________
Debut
..........
fin
__________________________________________
debut
...
P1(...) ;
Var1 ß F1(...) ;
...
fin.
__________________________________________

1.1. Eléments de base d’un algorithme :


Résoudre un problème avec la programmation, revient à l’analyser et à extraire ses données et ses traitements pour
déterminer les variables du programme et ses instructions.

A. Les instructions (le traitement) : sont généralement divisées en 2 parties :


Les instructions de base : +, -, *, /, affectation, comparaison, etc ...
Les structures de contrôle : on appel structure de contrôle toute instruction qui permet d’effectuer un groupe
d’actions sous condition(s), et permet donc d’orienter le déroulement d’un programme suivant l’évaluation
de ces conditions
Il existe plusieurs formes de structure de contrôle :
L’action conditionnelle ou alternative :
Si <Condition> alors
<Action 1>
Sinon
<Action 2 >
Fsi

M. bada 1
Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données

L’action répétitive ‘Tant que’ : L’action répétitive « Pour »


Tant que <Condition> faire Pour <nom_var> allant de
<Action> <val_initiale> à <val_finale> faire
end ; <Action>
end ;

NB : l’ensemble d’instructions dans le bloc <Action> étant répétées jusqu'à ce que la condition <condition> devienne Fausse
è il faut donc que la partie <Action> soit capable de modifier les paramètres intervenant dans la condition <Condition> afin
de sortir de la boucle Tantque.

L’action conditionnelle a choix multiple L’action conditionnelle a choix multiple


Case <nom_var> of Case ch of
1 : <Action1> ‘a’..’z’ : ecrire (‘lettre’) ;
2 : <Action2> ‘0’..’9’ : ecrire (‘chiffre) ;
n : <Action n> ‘+’ , ‘-’ . ‘*’... : ecrire (‘operateur) ;
.... default : ecrire (‘caractere special) ;
Default : <Action X> Fin ;
Fin ;

Les structures de contrôles sont très importantes pour contrôler le déroulement d’un Algorithme.

B. Structures de données
Les données du problème peuvent être simples ou complexes. La programmation doit disposer de structures pour
pouvoir les représenter, on parle alors de Structures de données

Structures simples : entier, réel, booléen, caractère, tableau, intervalle, etc...


Structures complexe : Liste, Pile, Fille, Arbre, etc...

2. Sous Programme :
Un sous programme (Fonction/Procédure) est un algorithme indépendant. L’appel de la fonction (resp. la procédure)
déclenche l’exécution de son bloc d’instructions.

NB :
Une fonction se termine en retournant une valeur.
Une procédure est une fonction qui retourne vide.

Passage de paramètres :
Par Valeur : pas de changement des variables effectifs.
Par Reference : peut entrainer un changement des variables effectifs.

3. La récursivité :

A. Définition : la programmation récursive est une technique de programmation qui remplace les instructions
de boucles (while, for, etc.) par des appels de fonction (une fonction qui s’appelle elle même avec des
paramètres différents).

L'idée est de diviser un problème P en sous-problèmes (certains de la même forme), de résoudre ces sous-
problèmes de manière directe si c'est possible sinon de la même manière que P (le problème initial), puis de
combiner le résultat de ces sous-problèmes pour résoudre le problème initial P.

M. bada 2
Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données

Exemple 1 : la fonction factorielle

n!= n (n-1) !

Factorielle (3)

Factorielle (3)
Debut
Factorielle ß 3* Factorielle (2)
fin

Factorielle (2)
Debut
Factorielle ß 2* Factorielle (1)
fin

Factorielle (1)
Debut
Factorielle ß 1* Factorielle (0)
fin

Factorielle (0)
Debut
Factorielle ß 0* Factorielle (-1)
fin

Jusqu'à -∞

B. Les conditions d’arrêt :


Puisqu'une fonction récursive s'appelle elle-même, il est impératif qu'on prévoie une condition d'arrêt à la
récursion, sinon le programme ne s'arrête jamais!

On doit toujours tester en premier la condition d'arrêt, et ensuite, si la condition n'est pas vérifiée, lancer un
appel récursif.

si n ≠ ,è n! = n * (n-1)! si n = 1 è n! = 1

Fonction factorielle (N : entier) : entier
Debut
Si (N=1) alors

Factorielle ç 1 ;
Sinon

Factorielle ß N* Factorielle (N-1)
fin

NB : Théoriquement, on peut toujours dé-récursiver un algorithme récursif, c’est-à-dire le transformer en algorithme itératif.
En pratique, ce n’est pas toujours facile!

M. bada 3
Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données




Factorielle (3)

Return : 3*2*1



Factorielle (3)
Debut
Factorielle ß 3* Factorielle (2)
fin Return : 2*1


Factorielle (2)
Debut
Factorielle ß 2* Factorielle (1)
fin Return : 1


Factorielle (1)
Debut
Factorielle ß 1
fin


Exemple 2 : La suite de Fibonacci

Les nombres de la suite de Fibonacci sont égaux à la somme des deux termes précédents, ils suivent donc la formule de
récurrence :

F(n+2)=F(n)+F(n+1)

Pour initialiser la suite, on prend généralement

F(0) = 0 et F(1) = 1

Calcul récursif de Fibonacci

fib(4) = fib(3) + fib(2)


è (fib(2) + fib(1)) + fib(2)
è ((fib (1) + fib (1)) + fib(1)) + fib(2)
è ((1 + fib(1)) + fib(1)) + fib(2)
è ((1 + 1) + fib(1)) + fib(2)
è (2 + fib(1)) + fib(2)
è (2 + 1) + fib(2)
è 3 + fib(2)
è 3 + (fib(1) + fib(1))
è 3 + (1 + fib(1))
è 3 + (1 + 1)
è3+2
è5

M. bada 4
Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données



Chapitre 1 : la complexité algorithmique


Exercice :
Ø écrire 2 fonctions différentes qui permettent de déterminer si un nombre entier N est premier ou composé.
Ø Donnez le NBR d’instructions de base en fonction de N.
Ø Supposons que N=11, et qu’une opération de division aura besoin de 1ms pour être exécuté. Calculez le
temps nécessaire pour exécuter cette fonction.
Ø Refaire la question précédente pour N= 1000003, N= 1000000019. Que pouvez vous conclure ?


1. Introduction :
Nous allons apprendre dans ce chapitre à travailler efficacement et rendre service aux utilisateurs de nos futurs ingénieux.
C'est souvent en pratique une importante réflexion dans la création de nos programmes. Le but de ce chapitre n'est pas de
faire de vous des experts en la matière, mais plutôt de vous donner une bonne introduction sur la question de complexité,
comprendre pourquoi certains programmes prennent beaucoup plus de temps à s'exécuter que d'autres.

Objectifs :
La théorie de la complexité (algorithmique) vise à répondre à ces besoins ;
• Classer les problèmes selon leurs difficultés.
• Classer les algorithmes selon leurs efficacités.
• Comparer les algorithmes résolvant un problème donné avant de faire un choix et sans les implémenter.

2. Efficacité d'un programme
L'efficacité d'un programme fait en réalité référence à une écriture de code intelligente, bien réfléchie. En d'autres
termes un bon algorithme.

L'efficacité se mesure sur deux dimensions :


• l’espace mémoire
• et le temps.

Le plus souvent, on ne peut pas avoir les deux dimensions en même temps. C'est-à-dire avoir un programme qui ne
prend pas assez d'espace en mémoire mais qui est moins rapide, ou un programme qui est très rapide mais qui prend
assez d'espace en mémoire.

2.1. Espace mémoire (Complexité Spatiale)


Dans la complexité spatiale, on s’intéresse à la question suivante :

De combien de mémoire le programme a t’il besoin?

Dans cette année nous ne nous intéressons pas à la complexité spatiale, car la mémoire croyez moi ce n'est pas ce qui
manque aux ordinateurs de nos jours.

2.2. Le temps (Complexité Temporelle)


Dans la complexité Temporelle, on s’intéresse à la question suivante :

Combien de temps d’exécution le programme dure t’il?

Question :
Supposons que nous aimerions répondre à la question suivante :
Combien de temps un algorithme implémenter par un programme prend à s'exécuter ?

M. bada 5
Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données

Réponse :

i. Méthode Empirique :
On peut par exemple lancer l’exécution du programme sur un ordinateur et chronométré l'exécution
de ce dernier; et dire plus tard que l'exécution a fait par exemple 4 minutes.

On peut par la suite, lancer un autre programme pour le même problème et obtenir par exemple 2
minutes de temps d'exécution.

Conclusion :
On peut conclure que le programme faisant 2 minutes est le meilleur !!! . ç Faux

Concrètement c'est une mauvaise manière de tester l'efficacité d'un programme car cette méthode
dépend :

– 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

Mais on n’a pas pris en compte la complexité des calculs du programme.

Comment faire?

ii. Méthode Mathématique


Pour ce faire, il faudra se baser sur une machine abstraite. C’est-à-dire compter le nombre
d'instructions basiques
T: IN à IN
Taille des entrées à Nombre d'instructions pour le calcul de cette taille d'entrées.

Une instruction est une opération qui prend un temps constant. Ex: une affection, une comparaison,
une division ...

3. A quoi on s’intéresse ? è pire des cas :



Pour essayer d'estimer le temps que prend un programme à s'exécuter on peut se servir du:
Meilleur cas (Temps minimum pour toutes les entrées possibles)
Pire cas (Temps maximum pour toutes les entrées possibles)
Cas moyen (Temps moyen pour toutes les entrées possibles)

Par exemple pour la recherche linéaire d'un élément dans un tableau :

12 34 3 22 10 5 45

Ø Le meilleur cas est que l'on trouve l'élément à la première comparaison.


Ø Le pire cas est que l'on parcoure tous les éléments de la liste et que l'élément recherché ne s'y trouve pas.
Ø Le cas moyen est que l'élément recherché se trouve à la 2eme, 3eme, 4eme position par exemple.

Nous nous intéresserons particulièrement au Pire Des Cas, car c'est celui qui arrive le plus souvent. Les deux autres
cas ne posent vraiment pas un grand problème.

M. bada 6
Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données

4. Complexité et ordre de grandeur :

4.1. La complexité (nombres d’instructions):


Pour calculer la complexité C(N), on applique les règles suivantes :

Ø Chaque instruction basique consomme une unité de temps ; (affectation d'une variable, comparaison, +, -, *,
=, ...). Les instructions de base prennent un temps constant, notée O(1)

Ø Chaque itération d'une boucle rajoute le nombre d'unités de temps consommées dans le corps de cette boucle

Ø Chaque appel de fonction rajoute le nombre d'unités de temps consommées dans cette fonction.

Ø Pour avoir le nombre d'opérations effectuées par l'algorithme, on additionne le tout ;

Exercice démonstratif N1 :
1) Que fait cette fonction?
2) Combien de temps prend cette fonction à s’exécuter en terme de nombres d'instructions ?

fonction fact (n :entier) : entier


debut
si (n>=0) alors
fß 1 ;
tantque (n>1) faire
fß f *n ;
nß n-1 ;
finsi ;

factßf ;

fin ;

Réponses :
1) cette fonction calcule le factoriel du nombre fourni en argument.
2) C(N) = 1 + 1+ 5(n-1) + 1 = 5n+2

Discussion :
Imaginons que N soit égal à 2000 nous aurons 5*2000 + 2= 10002 instructions. Malgré ce résultat, il est toujours
difficile d'exprimer la complexité du programme (difficile à classifier les algorithmes).

En effet, on cherche ou plutôt on doit avoir une seule variable de référence (pas une équation) car ce qui nous
intéresse c'est la croissance de cette variable en fonction des entrées du programme.

Dans l’exemple précédent: Notre variable de référence est N è pourquoi ? è On doit faire une
approximation par limite a une fonction connu : 5N+2 ≈ N. (Voir la parte : ordre de grandeur)

4.2. Ordre de grandeur :


La notation la plus utilisée pour exprimer (juste une notation pour la classification) la complexité d'un algorithme est
la notation O (ordre de...), qui dénote un ordre de grandeur.

M. bada 7
Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données

Soit f et g les fonctions réelles définies par les formules


f(x) = cos(x) +2
g(x)= x
On sait que g prend des valeurs aussi grandes que l'on veut au voisinage de l'infini.
Tandis que f ne peut prendre des valeurs qu'entre 1 et 3.

L'écart entre f et g au voisinage de l'infini ne cesse d'augmenter et n'est pas borné. è Dans ce contexte, on peut dire
que f est négligeable devant g au voisinage de l'infini (f << g ) , ou on écrit (notation de Landau)

f = O(g(x)) ou f ∈ O(g(x)) xà ∞

Pour trouver l’ordre de grandeur d’un algorithme, on doit calculer le nombre d’instruction dans le pire des cas et le
comparer avec un modèle de croissance.

4.2.1. Modèles de croissance (notions mathématique) :


En mathématique, il existe plusieurs modèles de croissance (selon la forme de la courbe):

1 : représente le modèle des fonctions constantes. Exp : f(N)= 5, f(N) = 8, f(N)= 35 : (ont tous la même
forme de courbe = une ligne parallèle avec l’axe des X).
N : représente le modèle des fonctions linéaire. Exp : f(N)= 3N+10, f(N)= N+30, f(N)= 12N-5 ...
2
N : représente le modèle des fonctions quadratique.
3
N : représente le modèle des fonctions cubique.
n
2 : représente le modèle des fonctions exponentielle.
Log (N) : représente le modèle des fonctions logarithmique.
N Log N : représente le modèle des fonctions sous-quadratique.

4.2.2. Comment trouver l’ordre de grandeur d’un algorithme :


Pour trouver à quelle modèle de complexité appartient notre algorithme, on doit :

Ø Calculer la complexité « C » (le nombre d’instructions) pour N et pour N+1, et faire la différence
entre les deux. (N : doit être le plus grand possible).

Ø Calculer f= C(N+1)- C(N) afin de trouver le modèle de croissance qui limite f.

Si f = C(N+1) – C(N) =

= 0 è fonction constante è O(1)
= 1 ou 2 ou 3 ... (un nombre fixe inferieur a N) è complexité linéaire è O(N)
2
= N ou 2N ou 3N+1 .... è Complexité quadratique è O(N )
2 3
= N .... è Complexité cubique è O(N )
= ε è Complexité Logarithmique è O(Log N)


Si (2N)- C(N) ≈ 1 è complexité Logarithmique è O(Log N)

M. bada 8
Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données


x n
Si C(N+1) = 2 * C(N) è complexité exponentielle è O(2 )

Dans l’exemple précédent,


C(N) = 5N+2
C(N+1) = 5(N+1)+2 = 5N +7
F= C(N+1) - C(N) = 5 è F ∈ O(N) ... 5 est négligeable a N (quand Nà ∞)

Donc la complexité du programme est O (N) ce qui veut dire que la complexité ou le temps d'exécution de cet
algorithme (nombres d’étapes) augmente linéairement en fonction de N.

Exercice démonstratif N2 (sans écrire l’algorithme) :

L’algorithme qui fait une recherche d’un élément X dans un tableau de taille N.
Dans le pire des cas l’élément n’existe pas ou bien il se trouve à la dernière case.
Dans ce cas on a besoin de comparer les N cases avec notre élément X è N comparaisons.
Si on augmente la taille du tableau à N+1 (on rajoute un élément) è N+1 comparaisons

Cad : Si on rajout 1 élément è une comparaison de plus sera nécessaire


Si on rajoute 2 éléments è 2 comparaisons de plus seront nécessaires

Dans ce cas la complexité est de l’ordre de N : O(N), car si on rajoute un élément on doit ajouter un nombre fixe
d’instruction (une seule comparaison).

Exercice démonstratif N3:

Debut
Xß 0 ;
Pour i allant de 1 jusqu'à N faire
Pour j allant de 1 jusqu'à N faire
XßX+1 ;
Fin pour ;
Fin pour ;
Fin.

On a deux boucles imbriquées, dont chacun va s’exécuter N fois è donc on a N*N itérations

Pour N= 100 , on va exécuter Xß X+1 100*100 fois = 10000 fois


Pour N+1= 101 on va rajouter presque 100 instructions qui est égal à N
si (on rajoute 1 à la donnée initiale è N instructions de plus) alors O(N2)

Ou

C(N+ 1) =(N+1)(N+1) = N2+2N+2


C(N) =N2
C(N+1)-C(N) = 2N+2 è O(N2)

Exercice démonstratif N4:


La recherche d’un élément X dans tableau trié de taille N par l’algorithme dichotomique.
La complexité de cet algorithme est de l’ordre de O(Log N). Pourquoi ?
Parce que si on rajoute N éléments (cad le double) è on rajoute une seule opération è C(2N)- C(N) ≈ 1

M. bada 9
Chapitre 1 : la complexité Université de Batna 2 Algorithmique et structures de données

4.2.3. Propriétés de Landau :



La notation O, dite notation de Landau, vérifie les propriétés suivantes :

- Si f=O(g) et g=O(h) alors f=O(h)


- si f=O(g) et k un nombre, alors k*f=O(g)
- si f1=O(g1) et f2=O(g2) alors f1+f2 = O(g2+g2)
- si f1=O(g1) et f2=O(g2) alors f1*f2 = O(g2*g2)

Selon la 1ere propriété :


O(log n) ⊂ O(n) ⊂ O(n log n) ⊂ O(n2) ⊂ O(n3) ⊂ O(2n)

M. bada 10

Vous aimerez peut-être aussi