introduction à la complexté algorithmique

32
Introduction à la Complexté Algorithmique Cours et exercices Filière SMI 2016-2017 Mustapha kchikech Département de Mathématiques et Informatique Faculté Polydsciplinaire-Safi Université Cadi Ayyad

Upload: others

Post on 21-Jun-2022

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Introduction à la Complexté Algorithmique

Introduction à

la Complexté Algorithmique

Cours et exercicesFilière SMI2016-2017

Mustapha kchikech

Département de Mathématiques

et Informatique

Faculté Polydsciplinaire-Safi

Université Cadi Ayyad

Page 2: Introduction à la Complexté Algorithmique

Table des matieres

Introduction iii

1 Complexite algorithmique 1

1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Complexite des algorithmes . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.2.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.2.2 Complexite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.2.3 Analyse des algorithmes . . . . . . . . . . . . . . . . . . . . . . . . 3

1.2.3.1 Taille des donnees . . . . . . . . . . . . . . . . . . . . . . 4

1.2.3.2 Le temps d’execution . . . . . . . . . . . . . . . . . . . . 5

1.2.3.3 Evaluation des couts . . . . . . . . . . . . . . . . . . . . . 5

1.2.3.4 Objectif . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.2.3.5 Evaluation du temps de calcul . . . . . . . . . . . . . . . 6

1.2.3.6 Evaluation de T(n) . . . . . . . . . . . . . . . . . . . . . 6

1.2.4 Notation asymptotique . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.2.4.1 Pourquoi une analyse asymptotique ? . . . . . . . . . . . 7

1.2.4.2 Definition Θ-Notation . . . . . . . . . . . . . . . . . . . 8

1.2.4.3 Definition, O-Notation . . . . . . . . . . . . . . . . . . . 9

1.2.4.4 Complexite d’un algorithme . . . . . . . . . . . . . . . . 9

1.2.4.5 Classes de complexite . . . . . . . . . . . . . . . . . . . . 9

1.2.4.6 Hierarchie entre les classes de complexite . . . . . . . . . 10

Page 3: Introduction à la Complexté Algorithmique

ii TABLE DES MATIERES

1.2.5 Exemples et exercices . . . . . . . . . . . . . . . . . . . . . . . . . 11

2 Reurrence 13

2.1 Presentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.2 Resolution des recurrences . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.2.1 Methode iterative . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.2.2 Methode de substitution . . . . . . . . . . . . . . . . . . . . . . . . 18

2.2.3 Methode generale . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

2.2.4 DIVISER-POUR-REGNER . . . . . . . . . . . . . . . . . . . . . . 20

2.3 Resolution des recurrences . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.3.1 Theoreme general : . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

2.3.1.1 Signification intuitive du theoreme . . . . . . . . . . . . . 22

2.4 Exercices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

Page 4: Introduction à la Complexté Algorithmique

Introduction

Ce polycopie presente une introduction sur la complexite algorithmique et des notions

sur la recurrence en algorithmique. L’objectif est de presenter des concepts fondamentaux

de la theorie de la complexite algorithmique qui offrent un ensemble d’outils permettant

d’analyser, de comparer et d’optimiser des algorithmes par la suite des programmes

informatique.

Par consequent, ce document met egalement a la disposition des etudiants un sup-

port de cours qui pourrait leur permettre d’acquerir et d’ameliorer leurs competences en

programmation.

Notons que ce document est un support pedagogique qui s’adresse principalement aux

etudiants de la filiere SMI semestre 4 de la Faculte Poly-disciplinaire de Safi, universite

cadi Ayyad. Il pourrait egalement servir comme support de cours aux etudiants d’autres

filieres.

Page 5: Introduction à la Complexté Algorithmique

iv Introduction

Page 6: Introduction à la Complexté Algorithmique

Chapitre 1

Complexite algorithmique

1.1 Introduction

— Le mot algorithme provient du nom du mathematicien arabe du IXe siecle, Mo-

hammed Ibn-Moussa Al-Khuwarizmi (livre d’arithmetique).

— Autant dire que les algorithmes sont connus et utilises bien avant les debuts de

l’informatique.

— Premier algorithme est l’Algorithme d’EUCLIDE (300 avant JC) pour calculer le

plus grand diviseur commun de deux entiers.

— La notion actuelle d’algorithme a ete elaboree par les logiciens des annees 1930

(Herbrand, Godel, Church et Turing).

— En 1968, Knuth publia le premier ouvrage The Art of Computer Programming

sur l’etude moderne des algorithmes informatiques.

— Il existe differentes facons de definir un algorithme. C’est pourquoi, nous presentons

ici quelques definitions qui peuvent donner une idee sur la notion d’algorithme.

— Un algorithme est une procedure de calcul bien definie, qui prend en entree une

valeur, ou un ensemble de valeurs, et qui produit, en sortie, une valeur ou un

ensemble de valeurs. Un algorithme est donc une sequence d’etapes de calcul per-

mettant de passer de la valeur d’entree a la valeur de sortie.

Page 7: Introduction à la Complexté Algorithmique

2 Complexite algorithmique

— Un algorithme est une procedure de calcul specifique permettant d’obtenir une

relation desiree entre l’entree et la sortie d’un probleme.

— L’algorithmique est la branche de l’informatique qui traite des algorithmes.

Exemple 1.

— Algorithmes d’Euclide :

Entree : deux entiers naturels a,b

Sortie : pgcd(a,b)

— Calcul de puissance :

Entree : deux entiers naturels a,n

Sortie : an

— Algorithmes de tri :

Entree : un tableau de n entiers tab = [a0, a1, · · · , an−1]

Sortie : un tableau de n entiers tab = [b0, b1, · · · , bn−1] t.q. b0 ≤ b1 ≤ · · · ≤ bn−1— Algorithme de recherche dans un arbre binaire de recherche :

Entree : un arbre binaire de recherche, une valeur v

Sortie : une reponse : la valuer figure oui ou non dans l’arbre

— Test de primalite :

Entree : un entier naturel n

Sortie : une reponse : n est premier oui ou non— · · ·

1.2 Complexite des algorithmes

1.2.1 Motivation

— Un algorithme est dit correct si, pour chaque donnee en entree, il doit fournir la

bonne sortie.

— Dans ce cas, on dit que l’algorithme (correct) resout le probleme donne.

— Pour resoudre informatiquement un probleme donne, on implante donc un al-

gorithme sur un ordinateur. C-a-d, l’algorithme sera reecrit avec un langage de

programmation.

Page 8: Introduction à la Complexté Algorithmique

1.2 Complexite des algorithmes 3

— Mais, pour un probleme donne, il existe bien souvent plusieurs algorithmes qui le

resout.

— Ces algorithmes different entre eux en termes d’efficacite. Ces differences peuvent

etre bien plus importantes que celles dues au materiel et au logiciel.

— Y a-t-il un interet a choisir des algorithmes ? et si oui comment choisir ?

1.2.2 Complexite

En informatique, la notion de complexite signifie deux concepts :

— la complexite des algorithmes : C’est l’etude de l’efficacite comparee des algo-

rithmes.

— En effet, la complexite introduit la notion de cout et montre qu’il ne suffit pas

de trouver une methode correcte pour resoudre un probleme, il faut aussi que

cette methode soit efficace.

— L’efficacite est mesuree par le temps et l’espace necessaire a un algorithme

pour resoudre un probleme.

— La complexite des problemes : C’est l’etude qui permet classification des problemes

en fonction des performances des meilleurs algorithmes connus qui les resolvent.

Pour notre cours, on parlera de la complexite c’est pour designer la complexite

des algorithmes.

Remarque 1.

1.2.3 Analyse des algorithmes

— La resolution informatique d’un probleme donne passe par un algorithme qui est

implemente par un langage de programmation.

— L’execution d’un programme a un cout. Il existe deux parametres essentiels pour

evaluer ce cout :

— le temps d’execution : la complexite temporelle

Page 9: Introduction à la Complexté Algorithmique

4 Complexite algorithmique

— l’espace memoire requis : la complexite spatiale

— Ainsi, analyser un algorithme est une operation qui consiste a prevoir les res-

sources necessaires (memoire, temps de calcul) au programme qui implemente cet

algorithme.

— Pour pouvoir analyser un algorithme, il faut avoir un modele de la technologie

qui sera employee.

— En algorithmique, les algorithmes sont analyses selon les calculs dans un modele

generique de machine a acces aleatoires (RAM=Random Access Machine), a pro-

cesseur unique.

— Dans le modele RAM, les instructions sont executees l’une apres l’autre, sans

operations simultanees.

— En resume,

Analyse des algorithmes ⇐⇒ etude de la complexite des algorithmes

1.2.3.1 Taille des donnees

Si l’on prend en compte tous les parametres : frequence d’horloge, nombre de proces-

seurs, temps d’acces disque,... l’estimation de ces ressources peut :

— etre assez compliquee, voire irrealisable,

— devenir irrealiste des que l’on change d’architecture.

— Pour cela on se contente souvent d’estimer l’influence de la taille des donnees sur

la taille des ressources necessaires. Ainsi,

La taille des donnees depend du probleme etudie

— On appelle les entrees ou les instances la taille des donnees necessaires a un algo-

rithme pour resoudre un probleme donne.

— La taille n va dependre du codage de ces entrees

Exemple : en binaire, il faut blog2(n)c+ 1 bits pour coder l’entier n.

— En pratique, on choisit comme taille la ou les dimensions les plus significatives.

— Exemple :

Page 10: Introduction à la Complexté Algorithmique

1.2 Complexite des algorithmes 5

— des matrices m× n : max(m,n), m.n, m+ n

— des listes, tableaux, fichiers : nombre de cases, d’elements

— des chaınes de caracteres : leur longueur

1.2.3.2 Le temps d’execution

— Le temps d’execution d’un algorithme sur une entree particuliere est le nombre

d’operations elementaire (affectations, comparaisons, operations arithmetiques),

executees.

— Le temps d’execution du programme depend :

— des donnees du probleme pour cette execution

— de la qualite du code engendre par le compilateur

— de la nature et de la rapidite des instructions offertes par l’ordinateur

— de l’efficacite de l’algorithme

— de l’encodage des donnees

— ... et aussi de la qualite de la programmation

— En general, on ne peut pas mesurer le temps de calcul sur toutes les entrees

possibles. Il faut trouver une autre methode d’evaluation.

— L’idee est d’evaluer le temps de calcul en fonction d’une grandeur n representant

la taille des donnees.

1.2.3.3 Evaluation des couts

— P : un probleme et M : une methode pour resoudre le probleme P

— Algorithme A : description deM dans un langage donne (algorithmique, C/C++,

Java, ...)

— Structures de controle :

— sequence (suite d’instructions)

— embranchement (ou selection) : if() ou switch()

— boucle (ou iteration) : for(); do...while(); while()

Page 11: Introduction à la Complexté Algorithmique

6 Complexite algorithmique

1.2.3.4 Objectif

— Evaluer le temps de calcul de A pour P

— Comparer A avec un autre algorithme A′

— L’evaluation :

— depends de la taille du probleme,

— doit etre independante de la machine utilisee.

1.2.3.5 Evaluation du temps de calcul

— La complexite d’un algorithme ou l’evaluation du temps de calcul d’un algorithme

est une mesure exprimee en fonction de la taille n des donnees :

T(n)=nombre d’operations elementaires

— On distingue trois sortes de complexites :

— la complexite dans le pire des cas : calcul du cout dans le pire des cas,

Tpire(n) =maxnT (n)

— la complexite en moyenne : on calcule le cout pour chaque donnee possible

puis on divise la somme de ces couts par le nombre de donnees differentes,

Tmoyenne(n) = 1n

∑nT (n)

— la complexite dans le meilleur des cas : on calcule le cout en se placant dans

le meilleur des cas.

Tmeilleur(n) =minnT (n)

— Remarque : En analyse de complexite, on etudie souvent le pire cas ce qui donne

une borne superieure de la complexite de l’algorithme.

1.2.3.6 Evaluation de T(n)

— Sequence (sommes des couts) :

Exemple 2.

Page 12: Introduction à la Complexté Algorithmique

1.2 Complexite des algorithmes 7

TraitementT1(n)

· · ·

TraitementTp(n)

⇒T (n) = T1(n) + T2(n) + · · ·+ Tp(n)

— Embranchement (Max des couts) :

Exemple 3.

si (condition logique) alors

TraitementT1(n)

sinon

TraitementT2(n)

⇒T (n) = max(T1(n), T2(n))

— Boucle (Somme des couts de chaque passage) :

Exemple 4.Tant que (condition logique) faire

TraitementTi(n)

Fin faire

⇒T (n) =k∑iTi(n)

k =nombre de repetition du traitement Ti(n).

1.2.4 Notation asymptotique

1.2.4.1 Pourquoi une analyse asymptotique ?

— En pratique une analyse precise d’un algorithme meme dans le pire des cas est

presque impossible (sauf pour un algorithme simple).

— La solution est d’etablir une approximation asymptotique du temps de calcul de

l’algorithme. Autrement, on fait une analyse asymptotique.

— On veut comparer des algorithmes differents sans les implementer, sans developper

des programmes. Pour faire ca on compare l’efficacite asymptotique des algo-

rithmes.

Page 13: Introduction à la Complexté Algorithmique

8 Complexite algorithmique

1.2.4.2 Definition Θ-Notation

Soient f et g deux fonctions de N dans R.

— On dit que g(n) est une borne approchee asymptotique pour f(n) et l’on ecrit

f(n) ∈ Θ(g(n)) s’il existe deux constantes strictement positives c1 et c2 telles que,

pour n assez grand, on ait

0 ≤ c1g(n) ≤ f(n) ≤ c2g(n)

— Ceci revient a dire que f(n) est egale a g(n) a un facteur constant pres.

— Pour indiquer que f(n) ∈ Θ(g(n)), on ecrit

f(n) = Θ(g(n))

Exemple 5.

— Montrons que f(n) = 12n

2 − 3n = Θ(n2).

— On doit trouver c1, c2, n0 > 0 telles que

Page 14: Introduction à la Complexté Algorithmique

1.2 Complexite des algorithmes 9

pour tout n ≥ n0c1n

2 ≤ 12n

2 − 3n ≤ c2n2

c1 ≤ 12 −

3n ≤ c2

Prenons c2 = 12 , on a

∀n ≥ 1,1

2− 3

n≤ c2

Prenons c1 = 114 , on a

∀n ≥ 7, c1 ≤1

2− 3

n

On prend donc n0 = 7, c1 = 114 et c2 = 1

2 .

1.2.4.3 Definition, O-Notation

Soient f et g deux fonctions de N dans R.

— On dit que g(n) est une borne superieure asymptotique pour f(n) et l’on ecrit

f(n) ∈ O(g(n)) s’il existe une constante strictement positive c telle que pour n

assez grand on ait

0 ≤ f(n) ≤ cg(n)

— Ceci revient a dire que f(n) est inferieure a g(n) a une constante pres et pour n

assez grand.

— Pour indiquer que f(n) ∈ O(g(n)), on ecrit

f(n) = O(g(n))

1.2.4.4 Complexite d’un algorithme

— Un algorithme A resout un probleme P en temps O(f(n)) si pour toute instance

de taille n, l’algorithme retourne une solution correcte avec un cout O(f(n)).

— La nature de la fonction f(n) definie la classe de complexite de l’algorithme A.

1.2.4.5 Classes de complexite

Lors de l’analyse de complexite, on essaie de se ramener aux classes suivantes :

Page 15: Introduction à la Complexté Algorithmique

10 Complexite algorithmique

— temps constant :Cout : O(1) Exemple : addition, affectation...

— Complexite logarithmique : Cout : O(log(n))

Exemple : recherche dichotomique dans un tableau trie A[1...n]

— Complexite lineaire : Cout : O(n) Exemple : calcul du produit scalaire de deux

vecteurs de Rn

— Complexite quasi-lineaire : Cout : O(nlog(n))

Exemple : Tri par fusion

— Complexite polynomial : Cout : O(nk), k > 1, pour k = 2, on parle de la Com-

plexite quadratique Exemple : Multiplication de deux matrices carrees d’ordre n :

O(n3)

— Complexite exponentielle : Cout : O(an) avec a > 1

Exemple : Tours de Hanoı

1.2.4.6 Hierarchie entre les classes de complexite

On peut etablir une hierarchie entre les classes de complexite du plus petit au plus

grand :

— O(1)→O(log(n))→O(n)→O(nlog(n))→O(n2)→O(nk)→O(an)

Page 16: Introduction à la Complexté Algorithmique

1.2 Complexite des algorithmes 11

k > 2, a > 1.

— Comparaison :

1.2.5 Exemples et exercices

1. Quelle est la complexite de ces parties de programme ?

somme=0;

for(i=1; i<=n; i++)

somme += n;

——————————————-

somme=0;

for (j=1; j<=n; j++)

a for (i=1; i<=n; i++)

a somme++;

for (k=0; k<n; k++)

a A[k] = k;

——————————————-

somme = 0;

for (i=1; i<=n; i++)

a for (j=1; j<=i; j++)

somme++;

Page 17: Introduction à la Complexté Algorithmique

12 Complexite algorithmique

——————————————-

somme = 0;

for (i=1; i<=n; i*=2)

a for (j=1; j<=n; j++)

a somme++;

2. Pour chacun des problemes suivants, ecrire en langage C une fonction iterative

qui permet de le resoudre et donner sa complexite.

(a) Puissance n-eme d’un entier.

(b) Suite de Fibonacci.

(c) Tri des tableaux.

(d) Test de Primalite d’un entier.

Page 18: Introduction à la Complexté Algorithmique

Chapitre 2

Reurrence

2.1 Presentation

— Une recurrence est une equation ou une inegalite qui decrit une fonction a partir

de sa valeur sur des entrees plus petites.

— une fonction est recursive si elle fait appel a elle-meme d’une maniere directe ou

indirecte.

— Un algorithme est dit recursif si son temps de calcul peut etre decrit par une

recurrence.

Page 19: Introduction à la Complexté Algorithmique

14 Reurrence

— L’utilisation des algorithmes recursifs est une technique de programma-

tion qui permet de trouver des solutions d’une grande elegance a un

certain nombre de problemes.

— Dans un algorithme recursif, la recursivite doit s’arreter a un moment

donne (test d’arret). Autrement, l’execution va continuer indefiniment.

— Ce processus est connu sous le nom du processus de reduction qui a

chaque appel, on doit se rapprocher de la condition d’arret.

— Attention ! : lorsqu’elle mal utilisee, on peut creer un code de programme

totalement inefficace.

Remarque 2.

Suite de Fibonacci

— La suite de Fibonacci est definie par : u0 = u1 = 1

un+2 = un+1 + un si n ≥ 2

— Un algorithme recursif qui calcule le nieme terme de cette suite :

int fib(int n)

a if(n<=1)

a return 1;

a else

a return fib(n-1)+fib(n-2);

— Complexite :

— Soit T (n) =nombre d’additions effectuees par cet algorithme lors du calcul.

— T (n) verifie les equations suivantes :

Page 20: Introduction à la Complexté Algorithmique

2.2 Resolution des recurrences 15

T (0) = T (1) = 1

T (n) = T (n− 2) + T (n− 1) si n ≥ 2

— C’est une equation de recurrence ou chaque terme d’ordre ≥ 2 depend unique-

ment des 2 termes qui le precedent.

— La solution de l’equation de recurrence est

T (n) =5 +√

5

10

(1 +√

5

2

)n+

5−√

5

10

(1−√

5

2

)n

— T (n) =O((

1+√5

2

)n).

— La complexite de cet algorithme est donc exponentielle !

2.2 Resolution des recurrences

Dans ce chapitre, nous allons proposer trois methodes de resolution des recurrences,

c-a-d pour obtenir des bornes asymptotiques Θ ou O pour la solution.

— Methode iterative

— Methode de substitution

— Methode generale

Page 21: Introduction à la Complexté Algorithmique

16 Reurrence

— En pratique, quand on definit et resout des recurrences, on omet souvent

les parties entieres et les conditions aux limites.

— En fait, ces details n’affectent pas les bornes asymptotiques des

recurrences rencontrees dans l’analyse des algorithmes. En effet :

— On passe souvent sur le fait que les arguments des fonctions sont

des entiers. Normalement, le temps d’execution T (n) d’un algorithme

n’est definit que pour n entier puisque, dans la plupart des algo-

rithmes, la taille de l’entree a toujours une valeur entiere.

— Le plus souvent on ignore les conditions aux limites. Puisque le

temps d’execution d’un algorithme sur une entree de taille constante

est une constante, les recurrences sous-jacentes au calcul du temps

d’execution des algorithmes ont generalement T (n) = Θ(1) pour n

suffisamment petit. Ainsi, pour simplifier, on suppose generalement

que T (n) est constant pour n petit.

Remarque 3.

2.2.1 Methode iterative

— L’idee de la methode consiste a developper la recurrence en sommation.

— On utilise les techniques d’evaluation des sommations pour trouver les bornes a

la solution.

— Cette methode necessite plus de manipulations algebriques.

Exemple 6.

T (n) = 2T (n

2) + 2n+ 1

Page 22: Introduction à la Complexté Algorithmique

2.2 Resolution des recurrences 17

On developpe comme suit :

T (n) = 2n+ 1 + 2T (n

2)

= 2n+ 1 + 2(n+ 1 + 2T (n

4))

= 2n+ 1 + 2(n+ 1 + 2(n

2+ 1 + 2T (

n

4)))

= 3(2n) + 1 + 2 + 4 + 23T (n

4)

= · · ·

= 2in+i−1∑j=0

2j + 2iT (n

2i)

On arrive a T (1) lorsquen

2i= 1, c-a-d lorsque i = log(n). Ainsi,

T (n) = 2n log(n) +log(n)−1∑

j=02j + nT (1)

= 2n log(n) + n− 1 + nΘ(1)

= 2n log(n) + n− 1 + Θ(n)

Par consequent T (n) = O(n log(n))

Exemple 7.

T (n) = 3T (n

4) + n

On developpe comme suit :

T (n) = n+ 3T (n

4)

= n+ 3(n

4+ 3T (

n

42))

= n+ 3(n

4+ 3(

n

42+ 3T (

n

43)))

= n+3

4n+ (

3

4)2n+ 33T (

n

43)

= · · ·

=i−1∑j=0

(3

4)jn+ 3iT (

n

4i)

Page 23: Introduction à la Complexté Algorithmique

18 Reurrence

On arrive a T (1) lorsquen

4i= 1, c-a-d lorsque i = log4(n). Ainsi,

T (n) = 4n(1− (3

4)log4(n)) + 3log4(n)T (1)

= 4n(1− (3

4)log4(n)) + nlog4(3)Θ(1) car 3log4(n) = nlog4(3)

= 4n+ Θ(nlog4(3)) pour n assez grand (3

4)log4(n) ≈ 0

Par consequent T (n) = O(n)

2.2.2 Methode de substitution

Cette methode recouvre deux phases :

— On conjecture la forme de la solution : c-a-d on devine (par intuition) une idee

de la solution.

— On utilise une recurrence mathematique pour trouver les constantes et pour mon-

trer que la solution est correcte.

— Le nom de cette methode vient du fait que l’on substitue la reponse

supposee a la fonction quand on applique l’hypothese de recurrence aux

valeurs plus petites.

— Elle ne s’applique que lorsque la forme de la reponse est facile a deviner.

Remarque 4.

Exemple 8.

T (n) = 2T (n

2) + n

On conjecture (par intuition) que la solution est T (n) = O(n log(n)).

La methode consiste a demontrer que T (n) ≤ cn log(n) pour un choix approprie de la

constante c > 0.

On suppose que T (n

2) ≤ cn

2log(

n

2).

La substitution donne

Page 24: Introduction à la Complexté Algorithmique

2.2 Resolution des recurrences 19

T (n) ≤ 2(cn

2log(

n

2)) + n

≤ cn log(n

2) + n

= cn log(n)− cn log(2) + n

= cn log(n)− cn+ n

≤ cn log(n) si c ≥ 1

Comment conjecturer les solutions des recurrences ?

— Malheureusement, il n’existe pas de regle generale.

— Deviner une bonne solution ressort de l’experience, c-a-d se servir des

recurrences deja rencontrees. Par exemple si T (n) = 2T (n2 + 100) + n.

Pour n assez grand, T (n2 ) et T (n2 + 100) sont quasiment les memes. On

peut donc supposer que T (n) = O(n log(n)).

— Parfois, il suffit d’une petite manipulation algebrique pour faire resembler

une recurrence inconnue a une autre deja vue. Par exemple, on utilise un

changement de variables.

Exemple : Prenons T (n) = 2T (√n) + log(n).

Posons m = log(n) ⇒ n = 2m. On aura donc T (2m) = 2T (2m2 ) +m.

On pose S(m) = T (2m), on obtient une nouvelle recurrence

S(m) = 2S(m

2) +m ⇒ S(m) = O(mlog(m)).

D’ou T (n) = T (2m) = S(m) = O(mlog(m)) = O(log(n) log(log(n))).

— Et parfois, de l’intuition pure ! ! !

Remarque 5.

Exemple & exercice : La recherche dichotomique

— Verifier que le nombre d’iteration de l’algorithme de recherche dichotomique d’un

tableau de taille n est

T (n) = T (n

2) + 1

Page 25: Introduction à la Complexté Algorithmique

20 Reurrence

— Montrer que

T (n) = O(log(n))

2.2.3 Methode generale

La methode generale est une methode qui s’appuie sur le theoreme maıtre de la

complexite, il est connu comme Master theorem en anglais et on l’appelle Theoreme

general en francais.

— Elle est consideree comme une ”recette” pour resoudre les recurrences de la forme

T (n) = aT (n

b) + f(n),

ou a ≥ 1 et b > 1 sont des constantes, et f(n) une fonction asymptotiquement

positive.

— Elle permet d’analyser le temps d’execution T (n) (au pire des cas) d’un algorithme

recursif obtenu par l’approche ”DIVISER-POUR-REGNER”.

2.2.4 DIVISER-POUR-REGNER

— L’approche ”diviser-pour-regner” est une technique pour la conception des algo-

rithmes.

— En effet, un algorithme base sur l’approche ”diviser-pour-regner”

1. separe le probleme en plusieurs sous-problemes semblables au probleme initial

mais de taille inferieure,

2. resolve les sous-problemes de facon recursive,

3. combine toutes les solutions pour produire la solution du probleme original.

— Le principe de l’approche ”diviser-pour-regner” se base sur trois etapes a chaque

niveau de recursivite :

1. Diviser le probleme en un certain nombre de sous-problemes.

Page 26: Introduction à la Complexté Algorithmique

2.3 Resolution des recurrences 21

2. Regner sur les sous-problemes en les resolvant recursivement.

Si la taille d’un sous-probleme est assez reduite, on peut le resoudre directe-

ment.

3. Combiner les solutions aux sous-problemes en une solution complete pour le

probleme initial.

Problème Solution

sous-problème 1

sous-problème 2

sous-problème j

sous-problème p diviser régner

solution 1

solution 1

solution 1

solution 1combiner

Problème Solution

sous-problème 1

sous-problème 2

sous-problème j

sous-problème p diviser régner

solution 1

solution 1

solution 1

solution 1combiner

2.3 Resolution des recurrences

— La recurrence de la forme T (n) = aT (nb ) + f(n), decrit le temps d’execution d’un

algorithme qui divise un probleme de taille n en a sous-problemes, chacun de taillen

b.

— Les a sous-problemes sont resolus recursivement, chacun dans un temps T (nb ).

— f(n) = D(n) + C(n) represente le cout induit par la decomposition du probleme

(D(n)) et la combinaison des resultats des sous-problemes (C(n)).

Page 27: Introduction à la Complexté Algorithmique

22 Reurrence

2.3.1 Theoreme general :

Soient a ≥ 1 et b > 1 deux constantes, soit f(n) une fonction et soit T (n) definie

pour les entiers n ≥ 0 par la recurrence

T (n) = aT (n

b) + f(n),

T (n) peut alors etre bornee asymptotiquement de la facon suivante.

1. Si ∃ε > 0 t.q. f(n) = O(nlogb(a)−ε) alors T (n) = Θ(nlogb(a)).

2. Si f(n) = Θ(nlogb(a)) alors T (n) = Θ(nlogb(a)log(n)).

3. Si ∃ε > 0 t.q. f(n) = Ω(nlogb(a)+ε) et si ∃c < 1 t.q. af(nb ) ≤ cf(n), pour

n suffisamment grand, alors T (n) = Θ(f(n)).

f(n) = Ω(g(n)) si ∃c > 0 t.q. pour n assez grand on ait 0 ≤ cg(n) ≤ f(n)

Theoreme 1.

2.3.1.1 Signification intuitive du theoreme

Dans chaque cas, on compare la fonction f(n) a la fonction nlogb(a). La solution de la

recurrence est determinee par la plus grande des deux.

— Cas 1 : nlogb(a) est la plus grande T (n) = Θ(nlogb(a)).

— Cas 2 : f(n) est la plus grande T (n) = Θ(f(n)).

— Cas 3 : f(n) = nlogb(a), T (n) = Θ(nlogb(a)log(n)).

Le theoreme general ne couvre pas toutes les possibilites pour f(n).

Remarque 6.

Exemple 9.

T (n) = 9T (n

3) + n

Page 28: Introduction à la Complexté Algorithmique

2.4 Exercices 23

Pour cette recurrence, on a a = 9, b = 3 et f(n) = n.

On a donc nlogb(a) = nlog3(9) = Θ(n2) et f(n) = n = O(nlog3(9)−ε), avec ε = 1.

D’apres le cas 1 du theoreme general, on peut dire que T (n) = Θ(n2).

Exemple 10.

T (n) = T (2n

3) + 1

Pour cette recurrence, on a a = 1, b = 32 et f(n) = 1.

On a donc nlogb(a) = n(log 3

2(1))

= n0 = 1. On est dans le cas 2 puisque f(n) =

Θ(nlogb(a)) = Θ(1).

La solution de la recurrence est donc T (n) = Θ(log(n)).

Exemple 11.

T (n) = 3T (n

4) + n log(n)

Pour cette recurrence, on a a = 3, b = 4 et f(n) = n log(n).

On a donc nlogb(a) = nlog4(3) = O(n0.793). Puisque f(n) = Ω(nlog4(3)+ε), avec ε ' 0.2, on

est dans le cas 3.

Pour n suffisamment grand, a f(n4 ) = 3n4 log(n4 ) ≤ 3n

4 log(n) = c f(n) avec c = 34 < 1.

Par consequent, D’apres le cas 3, on peut dire que T (n) = Θ(n log(n)).

Exemple 12.

T (n) = 2T (n

2) + n log(n)

On a a = 2, b = 2 et f(n) = n log(n). On a donc nlogb(a) = nlog2(2) = n. Dans ce cas, le

theoreme general ne s’applique pas a la recurrence. En effet,

On pourrais penser que le cas 3 s’applique, puisque f(n) est plus grande asymptotique-

ment que nlogb(a) = n. Le probleme est que f(n)

nlogb(a)= log(n) est asymptotiquement plus

petit que nε, ∀ε > 0.

2.4 Exercices

Exercice 1 :

Page 29: Introduction à la Complexté Algorithmique

24 Reurrence

Pour chacune des fonctions suivantes, determiner le temps de calcul dans le pire des

cas et en O() en justifiant votre reponse :

1. int fonct1(int n) 2. int fonct2(int n)

int i,j,s=0; int i,j,s=n;

for(j=30;j>10;j--) for(i=200;i>100;i-=20)

for(i=n/2;i>0;i-=2) for(j=n;j>=n-4;j-=2)

s*=2; s/=2;

return s; return s;

3. int fonct3(int n) 4. int fonct4(int n)

int i,j=1,s=0; int i=0,j,s=0;

while(j<n) do

j=i++;

for(i=1;i<n*n;i*=2) while(j<2*i)

s++;

j++; s++;

j+=3;

return s;

while(i<n);

return s;

5. int fonct5(int n) 6. int fonct6(int n)

if(n==0) if(n==0)

return 1; return 1;

return 2*fonct5(n/4); return fonct6(n-1)+fonct6(n-1);

Exercice 2 :

1. Donner la complexite des algorithmes iteratifs suivants :

Page 30: Introduction à la Complexté Algorithmique

2.4 Exercices 25

(a) Ajouter un element en tete, fin et quelconque, d’une liste chaınee.

(b) Supprimer un element en tete, fin et quelconque, liste chaınee.

(c) Rechercher un element quelconque dans une liste chaınee.

2. Evaluer la complexite des methodes iteratives proposees pour

(a) calculer la puissance nieme d’un entier,

(b) trier (selection, bulle, insertion) un tableau (ou une liste),

(c) calculer le nieme terme de la suite de Fibonacci,

(d) effectuer la recherche dichotomique dans une table,

(e) parcourir un arbre binaire et rechercher un element dans un arbre binaire AVL.

Exercice 3 :

1. Donnez des bornes asymptotiques approchees pour T (n) dans chacun des recurrences

suivantes :

(a) T (n) = 4T (n2 ) + n.

(b) T (n) = 4T (n2 ) + n3.

(c) T (n) = 2T (n2 ) +√n.

(d) T (n) =√nT (√n) + n.

2. Le temps d’execution d’un algorithme A1 resolvant un probleme P est decrit par

la recurrence T1(n) = 7T1(n2 ) + n2. Un autre algorithme A2 resolvant le meme

probleme P a un temps d’execution decrit par T2(n) = αT2(n4 ) +n2. Quelle est la

plus grande valeur de α telle que A2 soit asymptotiquement plus rapide que A1 ?

3. Soit une fonction definie par :

int fonct(int n)

if(n<2) return 1;

else return 4*fonct(n-1)-2*fonct(n-2);

Page 31: Introduction à la Complexté Algorithmique

26 Reurrence

(a) Soit T (n) le temps d’execution de la fonction fonct(). Exprimer T (n) en

fonction de T (n− 1) et T (n− 2).

(b) Calculer la complexite dans le pire des cas et en O() de cette fonction. Ce

programme est-il efficace ?

(c) Proposer une autre fonction en O(n) pour effectuer le meme traitement.

Exercice 5 :

1. Donner la complexite des algorithmes recursifs suivants :

(a) Supprimer un element quelconque dans une liste chaınee.

(b) Rechercher un element quelconque dans une liste chaınee.

(c) calculer la puissance nieme d’un entier,

(d) trier (fusion, rapide, tas) un tableau (ou une liste),

(e) calculer le nieme terme de la suite de Fibonacci,

(f) effectuer la recherche dichotomique dans une table.

2. Evaluer la complexite des differents algorithmes recursifs, vus au cours et en TD,

traitant les arbres binaires.

Exercice 4 :

Le tri fusion est une methode algorithmique basee sur la technique ”diviser pour

regner”. Le principe de cette methode peut etre decrit par l’algorithme recursif suivant :

— On divise la liste en deux parties presque de meme tailles,

— On trie les deux parties,

— On fusionne les deux parties.

Ce processus de la recursivite s’arrete une fois la decomposition des sous-listes donnent

des sous-listes composees d’un seul element et le tri est alors trivial.

1. Ecrire une fonction de prototype liste diviseListe(liste l) qui permet de

diviser une liste chaınee en deux sous-liste. Calculer sa complexite en fonction de

la taille de la liste d’entree.

Page 32: Introduction à la Complexté Algorithmique

2.4 Exercices 27

2. Ecrire une fonction de prototype liste FusionListe(liste lG,liste lD) qui

permet de fusionner deux listes. Calculer sa complexite.

3. Ecrire une fonction de prototype void triFusionListe(liste *l) qui permet

de trier une liste chaınee d’entiers. Calculer sa complexite en fonction de la taille

de la liste d’entree.