Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 6

Algorithmique 1 – L1 Université Clermont Auvergne

Fiche TD n°2 : Analyse d'algorithmes : complexité temporelle

Exercice 1 : Comparaison asymptotique

Soit n un nombre entier positif. On se donne plusieurs égalités entre des expressions arithmétiques en fonction
de n. Parmi les notations de Landau o/O/Ω/Θ suivantes, insérez un symbole rendant l’égalité vraie lorsque n
tend vers l’infini. De plus, pour chaque expression, donnez des exemples où les autres symboles sont utilisés.

Exemple :
3n+4 = ...(n²) : les symboles o et O conviennent. On peut écrire 3n+4 = Θ(n) et 3n+4=Ω(1).

1) 5 + 2 2=…..( 2 ) 2) 3 log  + 6 + 1=….() 3) 4 log  + 2=….( )

4)  3 + 2=….( 2 ) 5)  5 + 2 =….(2  ) 6) 2 =….(3  )

7) 4 +  2 + 6 =….( ) 8) 4 4 + 7 3.7=….( 4 ) 9) 2 +2=….(2  )

Exercice 2 : Décompte exact du nombre d’opérations

On considère plusieurs algorithmes. Pour chacun d’entre eux, déterminez le nombre exact d’opérations
effectuées (on précisera pour chaque algorithme quelles opérations sont à compter).

Algorithme 1 : Algorithme 2 : Algorithme 3 :

Debut Debut Debut

int n := (3+7)/5 nombre tab[10] int n := 10


int m := 2+4+6 int i int i := 0
m := n*m-26 Pour i de 0 à 5 : TantQue i <= 16 :
tab[i] := 3*i+1 n--
Fin tab[0] := 2*tab[1] i += 2

Fin Fin

a) Pour l’algorithme 1, comptez le nombre d’affectations et le nombre d’opérations arithmétiques +,-,*,/


b) Pour l’algorithme 2, comptez le nombre d’opérations sur les tableaux
c) Pour l’algorithme 3, comptez le nombre d’affectations

Exercice 3 : Texte à trous : calculer le produit


On cherche à calculer la complexité de la fonction produit, dont le pseudo-code est fourni ci-dessous, qui
prend en argument un tableau de nombres et qui renvoie le produit de tous les nombres positifs apparaissant

1
Algorithmique 1 – L1 Université Clermont Auvergne
dans le tableau. On appellera n le nombre de cases dans le tableau passé en argument, et on comptera le nombre
de lectures dans le tableau en fonction de n. Complétez le texte à trous ci-dessous

Fun nombre produit(nombre tab[ ]) :


int i A chaque passage dans la boucle : on
effectue …. ou ….. lectures dans tab
nombre prod:=1
Pour i de 0 à longu(tab)-1 :
Si tab[i]>0: On passe exactement …. fois
dans la boucle Pour
prod:=prod*tab[i]
Retourner prod

A chaque passage dans la boucle Pour, on fait au plus …. lecture(s) dans le tableau (et dans le pire des cas, on
effectue vraiment …. lecture(s) dans le tableau à chaque passage dans la boucle, par exemple
lorsque …………………………………………………………………………….). On passe exactement …. fois
dans la boucle. Le nombre de lectures dans le tableau hors de la boucle est …. . Donc la complexité temporelle
(en termes de lectures dans le tableau) est ….... x ……… + ……= ……….….., c'est à dire d'ordre de grandeur
O(…..). On dit que cette complexité est d'ordre (rayer les mauvaises réponses):
constant/logarithmique/linéaire/quadratique/cubique/exponentiel/autre (à préciser).
Supposons que l'exécution de cet algorithme sur un tableau de 10 000 cases prenne 2 sec. Alors l'exécution de ce
même algorithme sur un tableau de 40 000 cases prendra ……… sec.

Exercice 4 : Algorithmes de base sur les tableaux


On considère deux algorithmes sur des tableaux de nombres : maxTab et indiceDe

Fun nombre maxTab(nombre tab[ ]) : Fun nombre indiceDe(nombre tab[ ], nombre cible) :
int i int i

int maxJusquIci:=tab[0] Pour i de 0 à longu(tab)-1 :

Pour i de 1 à longu(tab)-1 : Si tab[i]==cible:

Si tab[i]>maxJusquIci: Renvoyer i

maxJusquIci:=tab[i] Renvoyer -1

Renvoyer maxJusquIci

Pour chacun des algorithmes :


1) donnez les spécifications, à savoir ce que fait l’algorithme par rapport au tableau d’entrée

2
Algorithmique 1 – L1 Université Clermont Auvergne
2) donnez l'ordre de grandeur de la complexité temporelle de l'algorithme, en fonction de n le nombre de cases
dans le tableau passé en argument. On comptera une opération élémentaire pour chaque lecture ou écriture dans
une case de tableau, ainsi qu'une opération élémentaire pour accéder à la taille du tableau.

Exercice 5 : Somme jusqu'ici


On propose deux algorithmes différents qui donnent le même résultat : ils prennent en entrée chacun deux tableaux
de nombres tab1 et tab2 (supposés de même taille), et remplissent chaque case i de tab2 avec la somme des
nombres apparaissant dans les cases 0 à i de tab1.
Proc remplirSommev1(nombre tab1[ ], nombre tab2[ ]):
nombre somme:=0
int i
Pour i de 0 à longu(tab1)-1:
somme:=somme+tab1[i]
tab2[i]:=somme

Fun nombre sommeJusqua(nombre tab[ ], int derniereCaseACompter):


// fonction auxiliaire pour la v2. Renvoie la somme des cases du tableau de 0 à l'indice indiqué.
nombre somme:=0
int j
Pour j de 0 à derniereCaseACompter:
somme:=somme+tab[j]
Renvoyer somme

Proc remplirSommev2(nombre tab1[ ], nombre tab2[ ]):


int i
Pour i de 0 à longu(tab1)-1:
tab2[i]:=sommeJusqua(tab1, i)

Le but est de comparer l'efficacité de ces deux algorithmes. On appellera n la taille des tableaux et on comptera
le nombre de lectures et d'écritures dans des cases de tableau en fonction de n (pour simplifier cette fois-ci, on ne
comptera pas les appels à longu mais en théorie, il faudrait).
(a) Si tab1 contient 8 | -2 | 6 | 5 | -1, et que tab2 est un tableau à 5 cases vides, que contient tab2 après l'appel
remplirSommev1(tab1, tab2) ?
(b) Donnez l'ordre de grandeur de la complexité temporelle de remplirSommev1 et remplirSommev2.
(c) On suppose, pour simplifier, que l'on peut faire 1 000 opérations par seconde. Complétez la phrase
suivante : pour des tableaux à n=100 cases, l'algorithme remplirSommev1 prendra …. sec. Pour des
tableaux à N=800 cases, l'algorithme remplirSommev1 prendra …. sec, c'est-à-dire qu'en multipliant la
taille du tableau d'entrée par 8, on multiplie par ……. le temps d'exécution. Pour des tableaux à n=100
cases, l'algorithme remplirSommev2 prendra …. sec. Pour des tableaux à N=800 cases, l'algorithme
remplirSommev2 prendra …. sec, c'est-à-dire qu'en multipliant la taille du tableau d'entrée par 8, on
multiplie par (environ) …. le temps d'exécution.

Exercice 6 : Tableau des nombres premiers


On considère deux algorithmes qui effectuent une même tâche et on cherche à comparer leur complexité. La tâche
est la suivante : étant donné un entier n ≥ 2, on veut renvoyer un tableau contenant n+1 cases représentant les
entiers 0,1,…,n où chaque case indique si l’entier correspondant est premier ou non. Autrement dit, la case i vaut

3
Algorithmique 1 – L1 Université Clermont Auvergne
Vrai si i est un nombre premier, Faux sinon. On rappelle qu’un nombre premier est un nombre divisible par
uniquement deux valeurs, à savoir 1 et lui-même. On considère que 0 et 1 ne sont pas des nombres premiers.
Algorithme 1 : Algorithme 2 :

int[ ] nb_premiers_v1(int n) : int[ ] nb_premiers_v2(int n) :


bool t[n+1] bool t[n+1]
tab[0] := Faux tab[0] := Faux
tab[1] := Faux tab[1] := Faux
tab[2] := Vrai tab[2] := Vrai
int k, i int k, i
Pour k de 3 à n : Pour k de 3 à n :
t[k] := Vrai t[k] := Vrai
Pour i de 2 à k-1 : Pour i de 2 à floor( ) :
Si k%i = = 0 : Si k%i = = 0 :
t[k] := Faux t[k] := Faux
Retourner tab Retourner tab

a) Evaluez la complexité en pire cas, en fonction de n, de l’algorithme 1 qui renvoie ce tableau. On comptera le
nombre d’opérations sur les tableaux.

b) Faites de même avec l’algorithme 2. De quelle astuce mathématique provient le gain de complexité ?
Pour vous aider dans les calculs de complexité, voici une inégalité qui pourraient vous servir :

 
( 4 + 5 − 3) ≤  ≤ 4 + 6
3 3
=1

Exercice 7 : Comprendre le logarithme (en base 2)


L’objectif de cet exercice est, étant donné un entier  ≥ 2, d’afficher les divisions successives de cet entier par 2.
L’affichage s’arrête lorsqu’on tombe sur un nombre impair. Par exemple :
- si  = 12, on affiche 12, 6, 3.
- si  = 28, on affiche 28,14,7.
- si  = 32, on affiche 32,16,8,4,2,1.

a) Ecrivez en pseudocode un algorithme qui remplit cet objectif. On appellera la fonction divisions_succ.

b) Pour un entier , quel est au plus le nombre d’entiers affichés par l’algorithme ? Pour quelles valeurs de n cette
borne est-elle atteinte ?

c) Déterminez la complexité de l’algorithme que vous avez proposé. Comparez avec la réponse à la question
précédente.

4
Algorithmique 1 – L1 Université Clermont Auvergne

Exercice 8: Triangle de Pascal


On donne ci-dessous le pseudo-code de deux algorithmes.

Une fonction parmi qui prend en argument deux entiers k et n, et qui renvoie la valeur du coefficient binomial
"k parmi n", définie ainsi :
 !
=
 !  −  !
Fun int parmi(int k, int n) : // renvoie la valeur du coefficent binomial "k parmi n"
Renvoyer facto(n)/(facto(k)*facto(n-k))
// en utilisant facto du catalogue. Note : ce n'est pas la manière la plus efficace de faire !

Une procédure trianglePascal qui prend en argument un entier nbLignes et qui affiche le triangle de Pascal
en s'arrêtant au bout du nombre de lignes indiqué par l'argument. Voici un exemple de triangle de Pascal avec 6
lignes :
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
En numérotant les lignes et les colonnes à partir de zéro, le nombre sur la ligne numéro n et la colonne numéro
k est le coefficient binomial "k parmi n". Par exemple, pour la colonne numéro 0, on a toujours "0 parmi n"=1,
et pour la colonne 1 on a toujours "1 parmi n"=n. De même, lorsque k=n, on a "n parmi n"=1 donc chaque ligne
se termine par un 1.

Proc trianglePascal(int n) :
int nLigne, k
Pour nLigne de 0 à n-1 :
Pour k de 0 à nLigne :
print(parmi(k, nLigne))
print("\n ") // ou print(Retour à la ligne) si vous préférez

Dans cet exercice, on comptera le nombre d'affectations.


(a) Donnez la complexité exacte de facto en fonction de la valeur de n, l'argument passé à la fonction. La
fonction facto se trouve dans le catalogue d’algorithmes du TD3 (page 5, TD3).
(b) Donnez la complexité exacte de parmi, en fonction des valeurs de k et n.
(c) Donnez l'ordre de grandeur de la complexité de trianglePascal en fonction de la valeur de n.
Vous pouvez vous aider de la formule suivante :
−1
1 1 1
2 = 3 − 2 + 
3 2 6
=0

(d) On décide d'utiliser nos connaissances en mathématiques pour avoir un algorithme plus efficace. Rappelez-
vous que:
 −1 −1
+  1 ≤  ≤  − 1
= −1 

1   = 0   = 

5
Algorithmique 1 – L1 Université Clermont Auvergne
Écrivez une fonction trianglePascalEfficace, qui prend en argument un entier n, et qui provoque le même
affichage que trianglePascal. Cependant, cette fois-ci, vous commencerez par déclarer un tableau à deux
dimensions à n lignes et n colonnes (en utilisant la syntaxe int tab[n][n]). Votre algorithme devra stocker
la valeur de "k parmi nLigne" dans la case tab[nLigne][k] avant de l'afficher.
(e) Quel est l'ordre de grandeur de la complexité temporelle de trianglePascalEfficace en fonction de la
valeur de n? (si vous avez écrit correctement votre algorithme, vous devez obtenir une complexité
temporelle quadratique en n). Est-ce plus efficace que trianglePascal?

Vous aimerez peut-être aussi