Introduction `a l’Algorithmique
N. Jacon
1 efinition et exemples
Un algorithme est une proc´edure de calcul qui prend en entier une valeur ou un ensemble de valeurs et qui
donne en sortie une valeur ou un ensemble de valeurs. C’est donc une s´equence d’´etapes qui transforme une
entr´ee en une sortie.
Par exemple, on peut consid´erer le probl`eme du tri de nombres dans un ordre croissant. L’entr´ee est
donc ici une suite de nnombres r´eels que l’on peut ´ecrire sous forme de liste :
(a1, . . . , an)
La sortie est la suite de ces nnombres ´ecrits dans l’ordre croissant c’est `a dire la suite des nnombres de la
liste r´eordonn´es :
(a0
1, . . . , a0
n)
de sorte que a0
1q0
2. . . a0
n. Ainsi, la liste (23,32,8,2,90,12,98) en entr´ee devra donner en sortie
(2,8,12,23,32,90,98). Le but est donc de d´eterminer un moyen pour passer de cette entr´ee `a cette sortie.
Un algorithme est dit correct si pour chaque entr´ee possible, il se termine en produisant la bonne sortie.
Dans ce cours, les algorithmes seront d´ecrits au moyen de programme ´ecrits en pseudo-code (tr`es proche du
Pascal, C, Algol). Ceci diff`ere n´eanmoins d’un langage de programmation classique :
1. le pseudo-code permet la description, la plus imag´ee possible, d’une suite d’actions qui ne d´ependent
d’aucune machine;
2. Un programme ´ecrit dans un langage est un texte tr`es lourd, tr`es pointilleux, destin´e `a un compilateur.
Il est ´ecrit dans un langage donn´e.
Prenons deux exemples : le premier est tr`es simple. On d´esire calculer la puissance d’un nombre r´eel quel-
conque sachant que l’on sait multiplier deux nombres r´eels quelconques. La donn´ee de d´epart est donc un
nombre r´eel aet un entier strictement positif n. On d´efinit une variable xqui sera initialis´ee `a 1 et donnera
notre r´esultat an`a la fin. On va ensuite multiplier xpar apendant n´etapes.
Algorithme 1: Calcul de puissance d’un nombre r´eel
1Nom : Puissance.
2Donn´ees : aR,nN;
3Variables : xR;
4x1;
5tant que n6= 0 faire
6a×x;
7nn1;
8fin
9esultat : x
Voici un deuxi`eme exemple o`u on d´esire calculer les racines d’une ´equation du second degr´e.
1
Algorithme 2: Calcul des racines d’un polynˆome du second degr´e
1Nom : Secondegre.
2Donn´ees : aR,bR,cR;
3Variables : ∆;
4si a= 0 alors
5si b= 0 alors
6si c= 0 alors
7esultat : R
8sinon
9esultat :
10 fin
11 sinon
12 esultat : {−c/b}
13 fin
14 fin
15 b24×a×c;
16 si <0alors
17 esultat : ;
18 fin
19 si ∆=0alors
20 esultat : {−b/(2 ×a)};
21 fin
22 si ∆=0alors
23 esultat : ({−b∆)/(2 ×a)),(b+∆)/(2 ×a)};
24 fin
Les principales instructions qui vont nous servir `a construire nos algorithmes sont les suivantes :
“Si Xalors Y” c’est `a dire, dans le cas o`u Xest v´erifi´e alors le programme ex´ecute la proposition Y.
“Tant que Xfaire Y” c’est `a dire, tant que la proposition Xest v´erifi´ee alors le programme ex´ecute la
proposition Y.
“ Pour iIfaire Y” c’est `a dire, le programme ex´ecute la proposition Ypour tous les ´el´ements dans
I.
Un dernier exemple tr`es li´e aux probl`emes de tri que nous rencontrerons par la suite : Etant donn´ee une
liste finie de nombres nomm´ee “Liste”, on d´esire ici trouver le plus petit ´el´ement de celle-ci. L’algorithme
de base est simple et suit exactement le proed´e intuitif que nous adoptons quand nous d´esirons r´esoudre ce
probl`eme par nos propres moyens :
On cr´ee une variable “mini” qui donnera `a la fin de la proedure le r´esultat voulu.
On prend le premier nombre de la liste “Liste” : Liste[1]. On assigne `a la variable “mini” ce premier
nombre.
Ensuite, on parcourt les nombres de le liste : Liste[2], Liste[3], etc. D`es que l’on rencontre un nombre
plus petit que notre “mini”, la variable “mini” devient alors ce nouveau nombre de la liste.
Quand on arrive `a la fin de la liste, on a termin´e : notre minimum est la valeur “mini”.
2
On suppose donc ici que l’on dispose d’une fonction Liste[k] qui nous renvoie le ki`eme ´el´ement de la liste. On
suppose aussi que l’on a une fonction “longueur” (que l’on peut facilement programmer : exercice !) qui nous
renvoie la longeur (c’est `a dire le nombre d’´el´ements) de la liste. On v´erifie que l’algorithme d´ecrit ci-dessus
est correct : on a bien test´e tous les ´el´ements de la liste et gard´e en m´emoire le plus petit de ceux-ci.
Enfin, on prendra bien soin de traiter le cas “pathologique” o`u la liste est vide (c’est `a dire lorsque sa
longueur est 0).
Algorithme 3: Recherche du minimum dans une liste.
1Nom : Minimum.
2Donn´ees : Liste.
3Variables : mini, nN,iN;
4nLongeur(Liste);
5si n= 0 alors
6esultat : ;
7fin
8mini Liste[1];
9pour i[2, n]faire
10 si Liste[i] <mini alors
11 miniListe[i];
12 fin
13 fin
14 esultat : mini
2 Performance d’un algorithme
Pour r´esoudre un probl`eme, il existe en g´en´eral plusieurs algorithmes possibles. Ces algorithmes ont en
principe diff´erents coˆuts en termes de :
temps d’ex´ecution (c’est `a dire en termes de nombre d’op´erations effectu´ees)
de taille m´emoire (taille n´ecessaire pour stocker les diff´erentes structures de donn´ees pour l’ex´ecution).
Ces deux concepts sont appel´es “complexit´e en temps et en espace”. On s’int´eressera ici principalement `a
la complexit´e en temps. La complexit´e permet donc de mesurer l’efficacit´e d’un algorithme et de le comparer
avec d’autre algorithmes r´esolvant le mˆeme probl`eme. Cette mesure repr´esente le nombre d’´etapes qui seront
n´ecessaires pour r´esoudre le probl`eme pour une entr´ee de taille donn´ee. Il y a deux types de complexit´e :
Etude du cas le plus d´efavorable : on estime le nombre d’op´erations r´ealis´e dans l’algorithme dans le
pire des cas.
Etude du cas moyen : on estime le nombre moyen d’op´erations n´ecessaires pour r´ealiser l’algorithme
en fonction de toutes les entr´ees possibles.
La seconde complexit´e est beaucoup plus difficile `a calculer que la premi`ere. Nous nous concentrerons ici `a
l’´etude de la complexit´e dans le cas le plus d´efavorable. En g´en´eral :
le temps d’ex´ecution d’une affectation ou d’un test est consid´er´e comme constant (ainsi les tests du
type “Si Xalors Y” sont consid´er´es comme constants)
le temps d’ex´ecution d’une s´equence d’instructions est la somme des temps d’ex´ecution qui la compose.
3
le temps d’ex´ecution d’une condition de type
Si Condition1 Alors Processus 1 sinon Processus 2
est ´egal au temps d’ex´ecution de “Condition1” ajout´e au maximum du temps d’ex´ecution de “Processus
1” et de “Processus 2”.
Le temps de Condition d’une boucle de type “tant que . . . faire . . . ou “Pour i= . . . faire . . . ” est
´egal `a la somme des coˆuts du test plus le coˆut du corps de la boucle.
Voici un exemple d’algorithme qui calcule la somme des carr´es d’une liste. La proedure donn´ee est
classique. Nous faisons ensuite une analyse de sa complexit´e.
Algorithme 4: Calcul d’une somme de carr´es des ´el´ements d’un tableau.
1Nom Somme2carres. Donn´ees : Liste.
2Variables : nN,iN, somme;
3nLongeur(Liste);
4si n= 0 alors
5esultat : ;
6sinon
7somme0;
8pour i[1, n]faire
9somme somme+L[i]×L[i] ;
10 fin
11 fin
12 esultat : somme.
Calculons la complexit´e de cet algorithme : on a une premi`ere affectation au d´ebut le premier “Si” fournit
une premi`ere instruction/affectation, le coˆut est constant, disons donc que l’on r´ealise 1 op´eration. Ensuite
nous avons un premier test qui coˆute une op´ration puis une affectation (`a l’int´erreur du “sinon”). Puis, on
va avoir ncalcul `a faire avec 3 op´erations `a chaque fois : une somme, une multiplication et une affectation.
On obtient 3nop´erations. On obtient 3n+ 3 op´erations. Pour simplifier, on dit que la complexit´e est en
O(n). Ceci signifie que le r´esultat trouv´e divis´e par nest inf`erieur `a une constante ce qui est le cas ici ... Par
exemple, l’algorithme 3 est aussi en O(n). L’algorithme 2 est en temps constant : on dit qu’il est en O(1).
Les principales complexit´es sont les suivantes. Elles sont ici class´ees en ordre croissant de coˆut :
O(1) : le temps constant,
O(log(n)) : complexit´e logarithmique,
O(n) : complexit´e lin´eaire,
O(nlog(n)),
O(n2), O(n3), . . . , O(np) : complexit´e polynˆomiale,
O(px) complexit´e exponentielle.
Bien sˆur, on cherche en pratique `a r´ealiser des algorithmes avec des complexit´es les moins couteuses possibles.
Ceci est fondamental. Voici un exemple permettant de se rendre compte de l’importance de ceci.
4
Example 2.1. On dispose d’un ordinateur Aqui ex´ecute un algorithme Ipermettant de r´esoudre un
probl`eme donn´e. On peut prendre pour exemple un probl`eme de tri, prob`eme que l’on ´etudiera par la suite.
Il s’agit dans ce cas de trier nnombres dans l’ordre croissant.
On suppose que cet algorithme demande 2n2op´erations de sorte que la complexit´e est en O(n2). Un
ordinateur Bex´ecute un algorithme 2 permettant de r´esoudre le mˆeme probl`eme grˆace `a 5nlog(n) op´erations.
Cet algorithme est donc en O(nlog(n)).
On suppose enfin que la puissance de calcul de l’ordinateur Aest de 109op´erations par seconde tandis que
celle de l’ordinateur Best de 106op´erations par seconde. Supposons qu’on veuille trier n= 1000 nombres.
L’ordinateur Ademande donc 2.10002
109= 2.103secondes.
L’ordinateur Bdemande donc 5.1000log(1000)
106'5.102secondes.
mais si on prend maintenant n= 106,
L’ordinateur Ademande donc 2.((10)6)2
109= 2000 secondes.
L’ordinateur Bdemande donc 5.106log(106)
106'100 secondes.
Consid´erons le probl`eme de calcul de la suite de Fibonacci. Initialement, cette suite ´etait destin´e `a
compter le nombre de lapins g´en´eration apr´es g´en´eration. Le mod`ele initial ´etait en effet : partant d’un
couple, combien de couples de lapins obtiendrons nous apr`es un nombre donn´e de mois sachant que chaque
couple produit chaque mois un nouveau couple qui ne devient lui-mˆeme “productif” qu’apr`es deux mois ?
Cette suite est enti`erement d´etermin´ee par la formule suivante :
N2, F (N) = F(N1) + F(N2), F (0) = F(1) = 1
L’algorithme qui nous vient imm´ediatement `a l’esprit pour r´esoudre ce probl`eme est le suivant :
Algorithme 5: Calcul de la suite de Fibonnacci (1).
1Nom Fibo1.
2Donn´ees : NN.
3si N1alors
4esultat : 1;
5sinon
6esultat : Fibo1(N1) + Fibo1(N2).
7fin
Quelle est la complexit´e de cet algorithme ? `a constante pr`es le nombre d’op´erations n´ecessaires est ici
f(N) avec
f(N) = f(N1) + f(N2).
Consid´erons la suite g(n) = f(N)/f(N1). Si cette suite converge vers x, alors xv´erife x= 1 + 1/x et
on a x= (1 + 5)/2. On peut ensuite montrer que cette suite est bien convergente. On obtient alors que
lorsque Ntend vers l’infini, f(N)/f(N1) tend vers xce qui implique que f(N) est en O(xN) ce qui est
une complexit´e exponentielle !
En fait, on voit qu’avec cet algorithme, on calcul beaucoup de chose plusieurs fois. Voici un algorithme
beaucoup plus rapide o`u tout n’est calcul´e qu’une et une seule fois. L’id´ee est de d´efinir une liste comportant
tous les ´el´ements de la suite de Fibonacci.
5
1 / 14 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !