Académique Documents
Professionnel Documents
Culture Documents
Cours de 3GI 2
Bibliographie
• D. Beauquier, J. Berstel, Ph. Chretienne. Elements d'algorithmique,
Masson, 2005.
• Thomas Cormen, Charles Leiserson, Ronald Rivest et Clifford Stein.
INTRODUCTION À L’ALGORITHMIQUE, Cours et exercices, Dunod
• Simon Harris and James Ross. Beginning Algorithms, Wiley
Publishing, Inc. 2006
• M. C. Gaudel, M. Soria et C. Froidevaux. Types de Données et
Algorithmes, Vol1. Analyse d’Algorithmes, Définition des Types de
Données, INRIA, Collection Didactique
Cours de 3GI 3
Introduction générale
• Définition des termes (algorithme et algorithmique)
• Définition formelle
• Définition informelle
• L’utilité de ce cours
• Le rôle des algorithmes par rapport aux autres technologies
informatiques
Cours de 3GI 4
Définitions
• Définition informelle du terme algorithme :
• procédure de calcul bien définie qui prend en entrée une valeur, ou un ensemble
de valeurs, et qui donne en sortie une valeur, ou un ensemble de valeurs.
• Un algorithme est donc une séquence d’étapes de calcul qui transforment
l’entrée en sortie.
• un algorithme se défini comme un outil permettant de résoudre un
problème de calcul bien spécifié.
• Algorithmique: ensemble des techniques et règles nécessaires pour
écrire les algorithmes et analyser leur efficacité
Cours de 3GI 5
Exemple
• Le problème de tri
• Définition formelle de ce problème
• Entrée : suite de n nombres (a1, a2, ..., an).
• Sortie : permutation (réorganisation) (a’1, a’2, ..., a’n) de la suite donnée en
entrée, de façon que a’1 a’2 · · · a’n.
Cours de 3GI 6
Algorithme correct vs incorrect
• Un algorithme est dit correct si, pour chaque instance en entrée, il se
termine en produisant la bonne sortie
• Un algorithme incorrect risque
• de ne pas se terminer pour certaines instances en entrée
• de se terminer sur une réponse autre que celle désirée.
Cours de 3GI 7
Typologie des algorithmes
• Le problème de tri
• Le projet du génome humain
• d’identifier les 100 000 gènes de l’ADN humain,
• de déterminer les séquences des 3 milliards de paires de bases chimiques qui constituent
l’ADN humain
• Internet permet d’accéder rapidement à toutes sortes de données. Tout cela
repose sur des algorithmes intelligents qui permettent de gérer et manipuler de
grosses masses de données.
• Exemples de problèmes à résoudre : recherche de routes optimales pour l’acheminement des
données
• Calcul matriciel
• Soit une suite A1, A2, . . . , An de n matrices, dont nous voulons calculer le produit A1A2 . . .
An.
Cours de 3GI 8
Structures de données
• Une structures de données est un moyen de stocker et organiser des
données pour faciliter l’accès à ces données et leur modification
• Aucune structure de données ne répond à tous les besoins
• Il est important de connaître les forces et limitations de plusieurs de ces
structures.
Cours de 3GI 9
Technique
• Ce cours vous enseignera des techniques de conception et d’analyse
d’algorithme, de façon que
• vous puissiez créer des algorithmes de votre cru,
• prouver qu’ils fournissent la bonne réponse
• et comprendre leur efficacité.
• Supposez que les ordinateurs soient infiniment rapides et que leurs
mémoires soient gratuites. Faudrait-il encore étudier les algorithmes?
Cours de 3GI 10
Efficacité
• les ordinateurs ne sont pas infiniment rapides. Quelque soit la
fréquence du processeur
• Si bon marché que puisse être la mémoire, elle n’est pas gratuite.
• Conséquence
• Le temps machine est donc une ressource limitée et il en est de même de
l’espace mémoire.
• Il faut utiliser ces ressources avec parcimonie,
• D’où l’intérêt
• des algorithmes performants, en termes de durée et d’encombrement qui vous
aideront à atteindre cet objectif
Cours de 3GI 11
Efficacité
• Soit un ordinateur rapide (ordinateur A) exécutant un algorithme donné en n²
• Supposez que l’ordinateur A exécute un milliard d’instructions par seconde
• Soit un ordinateur lent (ordinateur B) exécutant une version du même algorithme en nlgn
• l’ordinateur B n’exécute que dix millions d’instructions par seconde
• Ces deux machines doivent travailler sur un tableau d’un million de nombres.
• l’ordinateur A est 100 fois plus rapide que l’ordinateur B en termes de puissance de calcul brute.
• Pour rendre la différence encore plus sensible, supposez que le meilleur programmeur du monde
écrive la 1ère version de l’algo en langage machine pour l’ordinateur A et que le code résultant
demande 2n2 instructions pour traiter n nombres. (Ici, c1 = 2.)
• L’autre version, en revanche, est programmée pour l’ordinateur B par un programmeur médiocre
utilisant un langage de haut niveau avec un compilateur peu performant, de sorte que le code
résultant demande 50n lg n instructions (donc,c2 = 50). Pour traiter n nombres
• Faite le calcul ?!!!!!!!! ………
Cours de 3GI 12
Efficacité
T ( A) = 9
( ) 6 2
2. 10 instructions
= 2000 sec ondes
10 instructions / sec ondes
6 6
50.10 lg 10 instructions
T ( B) = 7 100 sec ondes
10 instructions / sec ondes
Avec un algorithme dont le temps d’exécution croît plus
lentement, même si le compilateur est médiocre la machine B
tourne 20 fois plus vite que la machine A
Cours de 3GI 13
Quiz
• Supposez que les ordinateurs soient infiniment rapides et que leurs
mémoires soient gratuites. Faudrait-il encore étudier les algorithmes ?
• On devrait étudier les algorithmes quelque soit la rapidité des
ordinateurs
• ne serait-ce que pour montrer que la solution ne boucle pas
indéfiniment et qu’elle se termine avec la bonne réponse.
Cours de 3GI 14
Algorithmes et autres technologies
• Même si une application n’emploie pas d’algorithmes au niveau de l’application elle-même, elle
s’appuie indirectement sur une foule d’algorithmes.
• L’application s’exécute sur des matériels performants ?
• La conception de ces matériels a utilisé des algorithmes.
• L’application tourne par dessus des interfaces graphiques ?
• Toutes les interfaces utilisateur graphiques reposent sur des algorithmes.
• L’application fonctionne en réseau ?
• Le routage s’appuie fondamentalement sur des algorithmes.
• L’application a été écrite dans un langage autre que du code machine ?
• elle a été traduite par un compilateur, un interpréteur ou un assembleur, toutes ces belles choses
faisant un usage intensif d’algorithmes.
• Les algorithmes sont au cœur de la plupart des technologies employées dans les ordinateurs
modernes.
Cours de 3GI 15
Exercice
• Quelle est la valeur minimale de n (resp la plage de valeurs) pour
laquelle un algorithme dont le temps d’exécution est 100n2 s’exécute
plus vite qu’un algorithme dont le temps d’exécution est 2n sur la
même machine ?
Cours de 3GI 16
Complexité d’un algorithme
Notation asymptotique
Principe de base
• Un algorithme est un ensemble d'opérations de calcul élémentaires,
organise selon des règles précises dans le but de résoudre un
problème donne.
• Les opérations élémentaires sont par exemple
• les opérations arithmétiques usuelles,
• les transferts de données,
• les comparaisons entre données,
• etc.
Cours de 3GI 18
Principe de base
• Ne considérer comme véritablement élémentaires que les opérations
dont le temps de calcul est constant, c'est-à-dire ne dépend pas de la
taille des opérandes.
• L'efficacité en temps d'un algorithme se mesure en fonction d'un
paramètre, généralement la « taille » du problème.
• Ce n'est évidemment pas le temps physique, exprimé en millisecondes ou en
heures qui importe.
Cours de 3GI 19
Exemples d’opérations élémentaires
• Recherche d’1 élément dans une liste
• Nombre de comparaison entre cet éléments et les entrées de la liste
• Recherche d’1 élément sur le disque
• Nombre d’accès à la mémoire secondaire
• Trier une liste d’éléments
• Le nombre de comparaisons entre 2 éléments
• Le nombre de déplacements (permutations)
• Multiplier deux matrices
• Nombre de multiplications arithmétiques
• Nombre d’additions arithmétiques
Cours de 3GI 20
Énoncé du problème
• Considérons un problème donné, et un algorithme pour le résoudre.
• Sur une donnée x de taille n, l'algorithme requiert un certain temps,
mesuré en nombre d'opérations élémentaires, soit c(x).
• Le coût en temps varie évidemment avec la taille de la donnée, mais
peut aussi varier sur les différentes données de même taille n
• Notre but est d'évaluer le coût d'un algorithme, selon certains
critères, et en fonction de la taille n des données.
Cours de 3GI 21
Calcul de la complexité
• Déterminer les opérations fondamentales, ensuite compter le
nombre d’opérations de chaque type
• Pas de règles générales pour ce comptage, mais quelques astuces
1. Séquence d’instruction: leurs nombres s’ajoutent
2. Branchements conditionnels: on ne sait pas a priori quelle branche sera
exécutée
Soit X: if C then I1 else I2 alors P(X) P(C)+ max(P(I1), P(I2))
Cours de 3GI 22
Calcul de la complexité
3. Pour les boucles, i étant l’incrément, P(i) le nombre d’opérations
fondamentales de la ième étape, Coût = P (i )
i
• Pour les appels de procédures non récursives, ordonner les
procédures de telle manière que chacune n’appelle que des
procédures dont le coût a déjà été évalué
• Pour les appels récursifs, il faut trouver la formule de récurrence.
Pour la factorielle par exemple:
T (n) = T (n − 1) + 1, n 1 et T (1) = 1
Cours de 3GI 23
Notation
• On évalue l'efficacité d'un algorithme en donnant l'ordre de grandeur
du nombre d'opérations qu'il effectue lorsque la taille du problème
qu'il résout augmente.
• On parle ainsi d'algorithme linéaire, quadratique, logarithmique, etc.
• Les notations de Landau sont un moyen commode d'exprimer cet
ordre de grandeur.
• la notation donne une majoration de l'ordre de grandeur;
• la notation en donne une minoration,
• la notation deux bornes sur l'ordre de grandeur.
Cours de 3GI 24
Représentation graphique
c2g(n) cg(n) f(n)
c1g(n)
n0 n0 n0
f(n)=(g(n)) f(n)=(g(n)) f(n)=(g(n))
Cours de 3GI 25
Notation
• On considère une fonction g:→. Etant donnée x0-,+,
• on désigne par O(g) l'ensemble des fonctions f pour lesquelles il
existe un voisinage V de x0 et une constante k > 0 tels que f(x)
kg(x) (x V )
• Exemple. Au voisinage de 0,
• x2 O(x);
• ln(1 + x) O(x)
Cours de 3GI 26
Notation
• Pour le cas x0=+, un intervalle est un ouvert ]a ,+[
• Par conséquent f O(g) au voisinage de + s’il existe 2 nombre k, a>0
tels que f(x) kg(x) pour tout x > a
• Exemple. Au voisinage de l’infini,
• x O(x2); ln(x) /x O(1); X+1 O(x)
• En effet
( )
P( x) = a 0 x k + a1 x k −1 + + a k on a P( x) x k au voisinage de +
P( x) = a 0 x k + a1 x k −1 + + a k ( a 0 + a1 + + a k )x k
Cours de 3GI 27
Exercices
f = ( g ) f = ( g )
f = ( g ) f = ( g ) f = ( g )
Cours de 3GI 28
La récursivité
Définition
• Technique de définition d’un problème en termes d’une ou de
plusieurs versions du même problème
• La solution au problème initial est construite à partir des résultats des
versions réduites
• Exemple: l’exponentiation
1 if n = 0 *+
a =
n
n −1
où a
a a if n 0
Cours de 3GI 30
Caractéristiques
• Éviter les références circulaires
• Les sous problèmes doivent être identiques au problème initial, mais
de taille plus réduite
• Les cas de base ont des solutions connues/directes
• Les solutions aux cas de base sont combinées d’une certaine façon
pour obtenir la solution au problème général
Cours de 3GI 31
Exemple: la factorielle
1 Fonction factorielle(n: in Entier): Entier
2 -- Factorielle de n
3
4 Nécessite : n >= 0
5 Début
6 Si n <= 1 Alors
7 Résultat < 1
8 Sinon
9 Résultat < n * factorielle(n-1)
10 FinSi
12 Fin
• Remarque : factorielle(n-1) est l’appel récursif.
Cours de 3GI 32
Fondement mathématique
• Le corps de la fonction factorielle précédente correspond à la définition
mathématique de la factorielle donnée sous forme de récurrence :
1 n 0,1
n! =
n (n − 1)! sinon
• Remarque :
• On pourrait mathématiquement utiliser la notation suivante pour définir la
factorielle n
n! = i = 1 2 n − 1 n
i =1
Cours de 3GI 33
Terminaison
• Danger :
• Il faut s’assurer que les appels récursifs s’arrêtent pour garantir la terminaison de
l’algorithme.
• Règle :
• Un algorithme récursif doit toujours faire apparaître deux éléments :
• le cas de base où l’on sait écrire le code sans nouvel appel récursif;
• le cas général dans lequel on fait des appels récursifs.
• Terminaison : Les appels récursifs doivent porter sur un problème de taille
strictement inférieure, supérieure à la taille du cas de base.
• Attention : Cette condition est suffisante mais pas nécessaire!
Cours de 3GI 34
Récursivité terminale
• Définition : Une fonction est récursive terminale quand le résultat de l’appel initial est directement
celui du dernier appel récursif.
• Règle : Aucune opération n’est réalisée sur le retour d’un appel récursif.
• 1 Fonction factorielle(n: in Entier; p: in Entier): Entier
• 2 Début
• 3 Si n <= 1 Alors
• 4 Résultat p
• 5 Sinon
• 6 Résultat factorielle(n-1, n * p)
• 7 FinSi
• 8 Fin
• Le calcul de la factorielle de 4 donne :
• fact(4) = f(4, 1)→ f(3, 4) → f(2, 12)→ f(1, 24)
• 24 24 24 24
Cours de 3GI 35
Récursivité terminale
• Remarque : Toute fonction récursive terminale peut être réécrite simplement en utilisant une itération.
• 1 Fonction factorielle(a: in Entier): Entier
• 2 Variable
• 3 n: Entier -- équivalent de a mais modifiable !
• 4 Début
• 5 n<a
• 6 Résultat 1
• 7 TantQue n > 1 Faire
• 8 Résultat n * Résultat
• 9 n n -1
• 10 FinTQ
• 11 Fin
• Remarque : On constate que Résultat est équivalent à p
Cours de 3GI 36
Récursivité non terminale
• Définition
• L'appel recursif n'est pas la dernière instruction et/ou elle n'est pas isolée (fait
partie d'une expression)
• plus(a,b)
• fonction plus (a,b : naturel) : naturel
• debut
• si b=0 alors
• retourner a
• sinon
• retourner 1+plus(a,b-1)
• finsi
• fin
Cours de 3GI 37
Récursivité mutuelle
• Définition
• On dit que deux algorithmes sont mutuellement récursifs si chacun des deux appelle l’autre
(éventuellement indirectement).
• Plus généralement, un ensemble d’algo est mutuellement récursif si la relation « f appelle g »
admet un cycle : f1 appelle ... appelle fn appelle f1.
• Exercice 1. La parité possède les propriétés suivantes :
• un nombre est pair s’il est nul ou si son prédecesseur est impair;
• un nombre est impair s’il est non nul et si son prédecesseur est pair.
• Écrire deux algo qui indiquent si un entier est pair ou impair.
Cours de 3GI 38
Solution
1. Fonction pair(n: in Entier): Booléen 1. Fonction impair(n: in Entier): Booléen
2. Est-ce que n est pair ? 2. Est ce que n est impair ?
3. Nécessite : n >= 0 3. Nécessite : n >= 0
4. Début 4. Début
5. Si n = 0 Alors 5. Si n = 0 Alors
6. Résultat VRAI 6. Résultat FAUX
7. Sinon 7. Sinon
8. Résultat impair(n-1) 8. Résultat pair(n-1)
9. FinSi 9. FinSi
10. Fin 10. Fin
Cours de 3GI 39
Problématiques récursives
• Il existe certains problèmes dont la définition est récursive. Ce genre
de problème se conçoit simplement à l’aide d’une fonction récursive.
• Les problèmes qui se solutionnent à l’aide de la récursivité peuvent
toujours être résolu à l’aide d’algorithme séquentiel non-récursif, mais
souvent cela est plus complexe
• Dans certains cas, l’algorithme récursif est très facile mais moins
rapide.
• Certains problèmes sont cependant très difficiles à régler de façon
non-récursive. La solution récursive est souvent facile à comprendre
(quoique difficile à trouver).
Cours de 3GI 40
Dérécursiver un algorithme
• Concerne uniquement les algorithmes récursifs terminal
• Soit les procédures suivantes
Cours de 3GI 43
Démonstration
• Or P(fy ) est equivalent a Q(fy ) • On peut généraliser l'utilisation de la variable
x
• Donc P(y) est equivalent a : • P(y) est donc équivalent a :
• si Cy alors • xy
• Iy
• si Cx alors
• sinon • Ix
• Jy • sinon
• x fy • Jx
• tant que non Cx faire • x fx
• Jx • tant que non Cx faire
• x fx • Jx
• fintantque • X fx
• Ix • fintantque
• Ix
• finsi
• finsi
Cours de 3GI 44
Démonstration
• Puis intégrer Jx et x fx dans la boucle • Puis « descendre » Ix après la
tant que boucle tant que
• P(y) est donc équivalent a : • P(y) est donc équivalent a :
• xy
• x y
• si Cx alors
• Ix • tant que non Cx faire
• sinon • Jx
• tant que non Cx faire • xfx
• Jx • fintantque
• xfx
• fintantque • Ix
• Ix
• finsi
Cours de 3GI 45
Démonstration
• Enfin supprimer la variable x
• P(y) est donc équivalent a :
• tant que non Cy faire
• Jy
• yfy
• fintantque
• Iy
• Or ce code est celui de Q(y)
• Donc :
• P est équivalent a Q
Cours de 3GI 46
Conclusion
• Les algorithmes récursifs sont simples (c'est simplement une autre
façon de penser)
• Les algorithmes récursifs permettent de résoudre des problèmes
complexes
• Il existe deux types de récursivités :
• terminale, qui algorithmiquement peut être transformée en algorithme non
récursif
• non terminale
• Les algorithmes récursifs sont le plus souvent plus gourmands en
ressource que leurs équivalents itératifs
Cours de 3GI 47
Diviser pour régner
Les algorithmes de tri
Présentation générale
• Méthode de résolution des problèmes en fournissant un
algorithme récursif
• La structure générale se subdivise en 3 étapes
1. La décomposition du problème en un certain nombre de sous-
problèmes de taille réduite
2. Les appels récursifs: appliquer récursivement la fonction sur
chacune des nouvelles entrées et retourner les k solutions s1, …,sk
3. La reconstitution des solutions partielles aux sous-problèmes en la
solution s au problème
Cours de 3GI 49
Multiplication des grands entiers
• Entier représenté sur des centaines d’octets
• Opérations élémentaires
• Lecture d’1 bit
• Modification d’1 bit
• L’accès au bit suivant
• Suppression du bit de poids faible (division par 2 noté n>>1)
• Insertion d’1 nouveau bit de poids faible (multiplication par 2 noté 2<<1)
Cours de 3GI 50
Premier algorithme
Function produit(a, b:entier):entier
resultat0;
tantque b 0 faire
si estImpair(b) alors
resultat addition(resultat,a);
a<<1; -- on multiplie a par 2
b>>1; -- on divise b par 2
fintq
retourner resultat;
Cours de 3GI 51
Analyse de l’algorithme
• La fonction addition est linéaire en la taille des entrées
• Le produit est quadratique
• (taille(a)taille(b))=(n²) avec n=taille(a)=taille(b)
• Peut-on faire mieux?
Cours de 3GI 52
Seconde version
• n=max(taille(a),taille(b))
• On suppose n pair
• a = a12n/2 + a2
• a1 est composé des n/2 bits de poids faible
• a2 des n/2 bits de poids fort
• Décomposons b de la même façon que a
• ab=a1b12n+(a1b2+a2b1)2n/2+a2b2
• ab= (a1+a2)(b1+b2)2n/2+a1b1(2n-2n/2)+a2b2(1-2n/2)
Cours de 3GI 53
Seconde version
• Pour multiplier a par b il faut
• 1. Décomposer l’entrée (a,b) en trois nouvelles entrée
(a1 + a2 , b1 + b2 ) (a1 , b1 ) (a2 , b2 )
• 2. Appliquer récursivement le produit sur chacune des entrées.
• 3. Recomposer le résultat s de la manière suivante
s = s1 2 n/2
+ s2 2 − s2 2
n n/2
+ s3 − s3 2 n/2
Cours de 3GI 54
Analyse de la complexité
• Décomposition (n)
• 3 appels récursifs sur des problèmes de taille n/2
• Reconstitution de la solution finale
• 2 additions, 2 soustractions, 4 décalages droits
• (n) pour chaque opération => (n) pour la reconstitution d’où
• f(n) = n + 3f(n/2) et f(1)=1
n n 3
0
3
1
3
ln 2 ( n )
ln( 3 / 2 )
f ( n ) = n + 3 + 3 2 + ... = n + + ... n = nn ln 2
2 2 2 2 2
f (n) = n ln 2 ( 3)
n1,58
Cours de 3GI 55
Proposition (Master Theorem)
f : → R+
• Soit
f ( n0 ) = d
avec n0 1, b 2 et des réels k 0, a 0, c 0, d 0
f ( n ) = af ( b ) + cn
n k
k
( )
f (n ) = n log n si a = b k
n ( )
log b a
si a b k
Cours de 3GI 56
Tri Rapide (Quicksort)
• Il est fondé sur le paradigme diviser-pour-régner
• les trois étapes du processus diviser-pour-régner sont employées pour trier un
sous-tableau typique A[p . . r].
1. Partitionnement/Diviser
• Le tableau A[p . . r] est partitionné (réarrangé) en deux sous-tableaux (éventuellement vides)
A[p . . q − 1] et A[q + 1. . r] tels que chaque élément de A[p . . q − 1] soit inférieur ou égal à
A[q] qui, lui-même, est inférieur ou égal à chaque élément de A[q + 1. . r].
• L’indice q est calculé dans le cadre de cette procédure de partitionnement.
2. Régner
• Les deux sous-tableaux A[p . . q−1] et A[q+1 . . r] sont triés par des appels récursifs au tri
rapide.
3. Combiner
• Comme les sous-tableaux sont triés sur place, aucun travail n’est nécessaire pour les
recombiner : le tableau A[p . . r] tout entier est maintenant trié.
Cours de 3GI 57
Algorithme
• TRI-RAPIDE(A, p, r)
1 si p < r alors
2 q ← PARTITION(A, p, r)
3 TRI-RAPIDE(A, p, q − 1)
4 TRI-RAPIDE(A, q + 1, r)
• Pour trier un tableau A entier, l’appel initial est TRI-RAPIDE(A, 1,
longueur[A]).
Cours de 3GI 58
Partitionnement
• Le point principal de l’algorithme est la procédure PARTITION, qui réarrange le sous-
tableau A[p . . r] sur place.
• PARTITION(A, p, r)
• 1 x ← A[r]
• 2i←p−1
• 3 pour j ← p à r − 1 faire
• 4 si A[j] x alors
• 5 i←i+1
• 6 permuter A[i] ↔ A[j]
• fsi
• fpour
• 7 permuter A[i + 1] ↔ A[r]
• 8 retourner i + 1
Cours de 3GI 59
Analyse de l’algorithme Partition
• Au début de chaque itération de la boucle des lignes 3–6, pour tout
indice k,
• 1) Si pki, alors A[k] x.
• Sur les lignes 7–8, l’élément pivot est permuté de façon à aller entre
les deux partitions.
• 2) Si i + 1 k j − 1, alors A[k] > x.
• 3) Si k = r, alors A[k] = x.
Cours de 3GI 60
Exercice
• Appliquer le partitionnement sur
le tableau suivant
• (2 8 7 1 3 5 6 4)
Cours de 3GI 61
Performance du tri rapide
• cas le plus défavorable
• la routine de partitionnement produit un sous problème à n−1 éléments et
une autre avec 0 élément.
• Supposons que ce partitionnement non équilibré survienne à chaque appel
récursif. Le partitionnement coûte (n)
• l’appel récursif sur un tableau de taille 0 rend la main sans rien faire, T(0) =
(1) et la récurrence pour le temps d’exécution est
• T(n) = T(n − 1)+T(0)+(n) = T(n − 1)+(n)= (n2).
Cours de 3GI 62
Cas défavorable vs tri par insertion
• Le temps d’exécution du tri rapide n’est donc pas meilleur, dans le cas
le plus défavorable, que celui du tri par insertion.
• En outre, ce temps d’exécution de (n2) se produit quand le tableau
d’entrée est déjà complètement trié
• Dans cette même situation le tri par insertion s’exécute en un temps
O(n).
Cours de 3GI 63
Cas favorable
• PARTITION produit deux sous-problèmes de taille non supérieure à
n/2
• La récurrence du temps d’exécution est alors T(n) 2T(n/2) + (n) ,
• la solution en est T(n) = O(n lg n).
Cours de 3GI 64
Tri par Tas
• Rappeler la structure d’arbre et la représentation sous forme d’un
tableau
• Revenir sur le propriétés des arbres complets
• Algorithme du tri pas tas
• Construction du tas
• Manipulation du tas
Cours de 3GI 65
Définition
• La structure de tas (binaire) est un tableau qui peut être vu comme un arbre
binaire presque complet
• Chaque nœud de l’arbre correspond à un élément du tableau qui contient la
valeur du noeud.
• Un tableau A représentant un tas est un objet ayant deux attributs :
• longueur[A], nombre d’éléments du tableau,
• et taille[A], nombre d’éléments du tas rangés dans le tableau A.
• A[1 . . longueur[A]] contient des nombres valides,
• Aucun élément après A[taille[A]], où taille[A] longueur[A], n’est un élément du tas.
Cours de 3GI 66
Exemple de tas
Cours de 3GI 67
Fonctions usuelles
• La racine de l’arbre est A[1]
• Étant donné l’indice i d’un noeud,
• PARENT(i) : retourner i/2
• décaler i d’une position binaire vers la droite
• GAUCHE(i): retourner 2i
• décaler simplement d’une position vers la gauche la représentation binaire de i
• DROITE(i): retourner 2i +1
• décaler d’une position vers la gauche la représentation binaire de i et en ajoutant
un 1 comme bit de poids faible
• Exercice de programmation:
• Écrire chacune de ces fonctions en langage C
Cours de 3GI 68
Propriété des tas
• Dans un tas max, la propriété de tas max est que, pour chaque noeud i autre que
la racine, A[PARENT(i)] A[i] ,
• En d’autres termes, la valeur d’un noeud est au plus égale à celle du parent.
• Ainsi, le plus grand élément d’un tas max est stocké dans la racine,
• et le sous-arbre issu d’un certain noeud contient des valeurs qui ne sont pas plus grandes que
celle du nœud lui-même.
• Un tas min est organisé en sens inverse ; la propriété de tas min est que, pour
chaque noeud i autre que la racine, A[PARENT(i)] A[i] .
• Le plus petit élément d’un tas min est à la racine.
Cours de 3GI 69
Hauteur d’un tas
• la hauteur d’un noeud dans un tas se définit comme le nombre d’arcs
sur le chemin simple le plus long reliant le noeud à une feuille
• On définit la hauteur du tas comme étant la hauteur de sa racine.
• Comme un tas de n éléments est basé sur un arbre binaire complet,
sa hauteur est (lg n)
Cours de 3GI 70
CONSERVATION DE LA STRUCTURE DE TAS
Cours de 3GI 71
Algorithme
• ENTASSER-MAX(A, i)
Exercice:
• 1 l ← GAUCHE(i) Illustrer l’action de ENTASSER-MAX(A, 3) sur
• 2 r ← DROITE(i) le tableau
• 3 si l taille[A] et A[l] > A[i] A = [27, 17, 3, 16, 13, 10, 1, 5, 7, 12, 4, 8, 9, 0].
• 4 alors max ← l
• 5 sinon max ← i
• 6 si r taille[A] et A[r] > A[max]
• 7 alors max ← r
• 8 si max i
• 9 alors échanger A[i] ↔ A[max]
• 10 ENTASSER-MAX(A, max)
Cours de 3GI 72
Analyse de l’efficacité
• en un noeud i donné, le temps (1) est nécessaire pour corriger les relations entre les éléments
A[i], A[GAUCHE(i)], et A[DROITE(i)], plus le temps d’exécuter ENTASSER-MAX sur un sous-arbre
enraciné sur l’un des enfants du noeud i.
• Les sous-arbres des enfants ont chacun une taille au plus égale à 2n/3 (le pire des cas survient
quand la dernière rangée de l’arbre est remplie exactement à moitié), et le temps d’exécution de
la procédure ENTASSER-MAX peut donc être décrit par la récurrence T(n) T(2n/3) + (1) .
• La solution de cette récurrence, d’après le théorème général est T(n) = O(lg n).
• On peut également caractériser le temps d’exécution de ENTASSER-MAX sur un noeud de hauteur
h par O(h).
• En effet, la descente s’effectue sur une branche de l’arbre
• Or nous avons vu que la hauteur h de l’arbre est le plus long chemin de la racine à une feuille où h=lg n
Cours de 3GI 73
CONSTRUCTION D’UN TAS
• On peut utiliser la procédure ENTASSER-MAX à l’envers pour convertir
un tableau A[1 . . n], avec n = length[A], en tas max.
• En remarquant que les éléments du sous-tableau A[(n/2 + 1) . . n]
sont tous des feuilles de l’arbre
• chacun est initialement un tas à 1 élément.
• La procédure CONSTRUIRE-TAS-MAX parcourt les autres noeuds de
l’arbre et appelle ENTASSER-MAX pour chacun.
Cours de 3GI 74
Algorithme
• CONSTRUIRE-TAS-MAX(A)
•1 taille[A] ← longueur[A]
•2 pour i ← longueur[A]/2 jusqu’à 1
•3 faire ENTASSER-MAX(A, i)
• Simuler l’exécution de Construire-Tas sur le tableau A=[4 1 3 2 16 9 10 14 8 7]
• Temps d’exécution (majorant)
• Chaque appel à ENTASSER-MAX coûte O(lg n),
• il existe O(n) appels de ce type.
• Le temps d’exécution est donc O(n lg n).
• Ce majorant, quoique correct, n’est pas asymptotiquement serré.
Cours de 3GI 75
ALGORITHME DU TRI PAR TAS
• TRI-PAR-TAS(A)
• 1 CONSTRUIRE-TAS-MAX(A)
• 2 pour i ← longueur[A] jusqu’à 2
• 3 faire échanger A[1] ↔ A[i]
•4 taille[A] ← taille[A] − 1
•5 ENTASSER-MAX(A, 1)
• La procédure TRI-PAR-TAS prend un temps O(nlgn)
• l’appel à CONSTRUIRE-TAS-MAX prend un temps O(nlogn)
• chacun des n −1 appels à ENTASSER-MAX prend un temps O(lg n).
Cours de 3GI 76
A éviter
• Quand ne pas utiliser l'approche diviser-pour-regner (avec
récursivité)
• Pour que l'approche diviser-pour-regner avec récursivité conduise à
une solution efficace, il ne faut pas que l'une ou l'autre des
conditions suivantes survienne :
1. Un problème de taille n se décompose en deux ou plusieurs sous-
problèmes eux même de taille presque n (par ex., n -1).
2. Un problème de taille n se décompose en n sous problèmes de taille
n/c (pour une constante c2).
Cours de 3GI 77
Travaux Pratiques
• Programmer les algorithmes vus en cours
• Tri rapide (par segmentation)
• Tri par Tas
• Recherche dichotomique dans un tableau trié
• Contraintes
• Langage de programmation: le C/Java
• Délai de réalisation: 14 jours
• Livrables: code sources, jeux de test, un fichier readme qui détaille
l’exploitation de votre programme
Cours de 3GI 78
Programmation dynamique
Cours de 3GI 79
Position du problème
Cours de 3GI 80
Position du problème
• Version récursive
• Utilise la technique DPR
• Duplication des calculs (cf. arbre d’appel des fonctions)
• Complexité en exponentielle
• Pour calculer Fib(n), Fib(n-k) est évalué k fois
• Problème
• Réutiliser le résultat d’un calcul précédent
• Eviter (éliminer) les redondances
• Solution
• Concevoir une structure pour mémoriser les résultats obtenus
Cours de 3GI 81
DPR vs Prog. Dynamique
• Les algorithmes DPR
• Partitionnent le problème en sous-problèmes identiques et indépendants qu’ils
résolvent recursivement
• Puis combinent leurs solutions pour résoudre le problème initial
• La programmation dynamique
• Résout des problèmes en combinant des solutions des sous problèmes
• « programmation » dans ce contexte fait référence à une méthode tabulaire et non à
l’écriture de code informatique
• Domaine d’application
• Recherche opérationnelle en particulier les problèmes d’optimisation
• Il s’agit de recherche une solution optimale (minimale ou maximale) dans l’ensemble
des solutions possibles
Cours de 3GI 82
Méthode de la programmation dynamique
• Les étapes suivies peuvent être résumées comme suit :
1. Caractériser la structure d’une solution optimale => obtention de l’équation
récursive liant la solution d’un problème à celle de sous-problèmes.
2. Définir récursivement la valeur d’une solution optimale
3. Calculer la valeur d’une solution optimale de manière ascendante (bottom-up) =>
remplissage de la table. Cette étape consiste à résoudre les sous-problèmes de
taille de plus en plus grandes, en se servant bien entendu de l’équation obtenue à
l’étape 1.
4. Construire une solution optimale à partir des informations calculées.
• Remarque
• Les étapes 1-3 forment la base d’une résolution de problème à la mode de la
programmation dynamique
• On peut omettre l’étape 4 si l’on a besoin que de la valeur d’une solution optimale
Cours de 3GI 83
Illustration 1: Suite de fibonacci
int function Fib(int n){
if (Fib(n) solution est dans la table) Suppression de la récursivité
return table[n] ; Espace mémoire O(n)
if (n<= 2)
return 1;
else {
sol = Fib(n-1) + Fib(n-2) int function Fib(int n){
sauvegarder sol dans table comme solution à Fib(n) ; F[1] =1 ; F[2] =1 ;
return (sol) ; For (i=2 ; i<=n ; i++)
} F[i] = F[i-1] + F[i-2];
} return (F[i]);
}
• Utiliser un vecteur Tab tel que Tab(i) stocke Fib(i)
• On les initialise à -1
• On ne calcule Fib(i) dans une descente que si Tab(i)==-1
• Espace mémoire O(n) Cours de 3GI 84
Fibonacci (version itérative)
• Cette version est aussi efficace si on calcule de manière ascendante
• Efficacité O(n)
• Espace mémoire O(1) => moins d’espace mémoire
int fib(int n) {
int a, b, i;
a =b = 1;
pour i de 2 à n faire {
aux = b;
b = a+b; // b contient fib(i)
a = aux; // a contient fib(i-1)
}
return b;
}
Cours de 3GI 85
Etude de quelques exemples
• Calcul du coefficient binomial
• Rendre la monnaie (distributeur automatique)
• Plus longue sous-chaine
• Applications:
1. Programmation: recherche de la plus longue sous-chaine dans une chaine
de caractères
2. Biologie: recherche des séquences d’ADN
• Multiplication chaînée de matrices
• Problème du voyageur de commerce/ Sac au dos
Cours de 3GI 86
Illustration 2: coef binomiale
𝑘−1 𝑘
𝐶𝑛𝑘 =ቊ𝐶𝑛−1 + 𝐶𝑛−1 𝑠𝑖 0 < 𝑘 < 𝑛
1 𝑎𝑢𝑡𝑟𝑒𝑚𝑒𝑛𝑡
Cours de 3GI 87
Coef. Binomial (version itérative)
int Comb(int n, int k){
// C matrice de (n+1) ligne × (k+1) colonnes
int[][] C = new int[n+1][k+1];
C[0,0] = 1;
for(int i=1; i <= n; i++)
for(int j=0; j <= min(i, k); j++)
if (j==0) || (j==i) Complexité: Θ(nk)
C[i,j] = 1; Espace Mémoire: Θ(nk)
else // j< i
C[i,j] = C[i-1,j-1] + C[i-1,j];
return C[n,k];
}
Remarque: un tableau à une dimension suffirait pour faire ces calculs (exercice)
Cours de 3GI 88
Graphes
Représentation et algorithmes
Définition
• Un graphe orienté G = (S;A)
• S est un ensemble fini S d'éléments appelé Sommets
• A SS dont les éléments sont appelés arcs.
• Un arc (x; y) représente une liaison orientée entre l'origine x et
l'extrémité y.
• Si (x; y) est un arc, y est un successeur de x, x est un prédécesseur de
y et si x = y
• l'arc (x; x) est appelé boucle.
Cours de 3GI 90
Définition
• Un graphe non oriente G = (S;A)
• S est un ensemble fini d'éléments appelés sommets
• A une famille de paires de S dont les éléments sont appelés arêtes.
• Etant donne un graphe oriente, sa version non orientée est obtenue
en supprimant les boucles et en substituant a chaque arc restant (x; y)
la paire {x; y}.
Cours de 3GI 91
Exemples d’application
• Gestion des réseaux de communication
• Réseau d’ordinateurs
• Carte de liaisons routières/aériennes/navales
• Ordonnancement des tâches
• contrainte de précédence entre deux tâches
• Systèmes à état
• possibilité pour un système de passer d'un état a un autre
• Plus généralement, les graphes interviennent chaque fois que l'on
veut représenter et étudier un ensemble de liaisons (orientées ou
non) entre les éléments d'un ensemble ni d'objets.
Cours de 3GI 92
Représentation
• Deux façons classiques de représenter un graphe
• par un ensemble de listes d’adjacences,
• par une matrice d’adjacences
• La représentation par listes d’adjacences est souvent préférée, car elle
fournit un moyen peu encombrant de représenter les graphes peu
denses
Cours de 3GI 93
Liste d’adjacence
• La représentation par listes d’adjacences d’un graphe G = (S, A)
consiste en un tableau Adj de #S listes, une pour chaque sommet de
S.
• Pour chaque u S, la liste d’adjacences Adj[u] est une liste des
sommets v tels qu’il existe un arc (u, v) A.
• Autrement dit, Adj[u] est constituée de tous les sommets adjacents à
u dans G
Cours de 3GI 94
Liste d’adjacence (Graphe non orienté)
Cours de 3GI 95
Liste d’adjacence (graphe orienté)
Cours de 3GI 96
Propriétés
• Si G est un graphe orienté, la somme des longueurs de toutes les listes d’adjacences vaut |A|, puisque
l’existence d’un arc de la forme (u, v) se traduit par la présence de v dans Adj[u].
• Si G est un graphe non orienté, la somme des longueurs de toutes les listes d’adjacences vaut 2|A|,
puisque si (u, v) est une arête, u apparaît dans la liste d’adjacences de v, et vice versa.
• Qu’un graphe soit orienté ou non, la représentation par listes d’adjacences possède la propriété avantageuse
de ne demander qu’une quantité de mémoire en O(max(S, A)) = O(S + A).
• Les listes d’adjacences peuvent aisément être adaptées aux graphes pondérés, c’est-à-dire aux graphes dont
chaque arc possède un poids associé, donné habituellement par une fonction de pondération w : A → R.
• Par exemple, soit G = (S, A) un graphe pondéré de fonction de pondération w. Le poids w(u, v) de l’arc (u, v)
A est tout simplement stocké avec le sommet v dans la liste d’adjacences de u.
• La représentation par listes d’adjacences est assez robuste, dans le sens où elle peut être modifiée pour
supporter de nombreuses variantes sur le graphe.
Cours de 3GI 97
Matrice d’incidence
• Un inconvénient potentiel de la représentation par listes d’adjacences
est que, pour déterminer si un arc (u, v) donné est présent dans le
graphe, il n’existe pas de moyen plus rapide que de rechercher v dans
la liste d’adjacences Adj[u] soit (|Adj[u]|)
• On peut remédier à cet inconvénient en représentant le graphe par
une matrice d’adjacences, ce qui se traduira par une utilisation
asymptotiquement plus importante de la mémoire soit (1)
Cours de 3GI 98
Matrice d’adjacence
• Pour la représentation par matrice d’adjacences d’un graphe G = (S, A), on
suppose que les sommets sont numérotés arbitrairement 1,2,...|S|.
• La représentation par matrice d’adjacences d’un graphe G consiste alors en une
matrice |S|×|S|, M=(aij) telle que
• aij = 1 si (i, j) A ,
• aij = 0 sinon .
• La matrice d’adjacences d’un graphe nécessite une quantité de mémoire en
(S2), quel que soit le nombre d’arcs du graphe.
• On remarque que la matrice d’adjacences pour un graphe non orienté est
symétrique par rapport à sa diagonale principale
Cours de 3GI 99
Matrice d’adjacence
k
w( p ) = w(vi −1 , vi )
i =1
0 si i = j
cij = si i j et (i, j ) A
(i, j ) si i j et (i, j ) A
Cours de 3GI 122
Algorithme de Dijkstra
• On construit un autre vecteur p pour mémoriser le chemin pour aller
du sommet 1 au sommet voulu.
• La valeur p(i) donne le sommet qui précède i dans le chemin.
• On considère ensuite deux ensembles de sommets, E initialisé à {1} et
T initialisé à {2, 3, ..., n}.
• À chaque pas de l'algorithme, on ajoute à E un sommet jusqu'à ce
que E = S de telle sorte que le vecteur donne à chaque étape le coût
minimal des chemins de 1 aux sommets de E.
• Initialisations
• 1 (j) = c1,j et p(j) = NIL, pour 1 j n
• 2 Pour 2 j n faire
• 3 Si c1,j < alors p(j) = 1.
• 4 E = {1} ; T = {2, 3, ..., n}.
• Itérations
• 5 Tant que T faire
• 6 Choisir i dans T tel que (i) est minimum
• 7 Retirer i de T et l'ajouter à E
• 8 Pour chaque successeur j de i, avec j dans T, faire
• 9 Si (j) > (i) + (i, j) alors
• 10 (j) = (i) + (i, j)
• 11 p(j) = i