Académique Documents
Professionnel Documents
Culture Documents
CONCEPTION
ETANALYSED'ALGORITHMES
Bouna Mohamed
Conception et Analyse d’algorithmes
Avant propos
L'Université virtuelle africaine (UVA) est fier de participer à l'amélioration de l'accès à
l'éducation dans les pays africains à travers la production de matériel didactique de qualité.
Nous sommes également fiers de contribuer aux connaissances mondiales comme nos
ressources pédagogiques sont pour la plupart accessibles de l'extérieur du continent africain.
Au nom de l'Université virtuelle africaine et notre patron, nos institutions partenaires, la Banque
africaine de développement, je vous invite à utiliser ce module dans votre établissement, pour
votre propre formation, de partager le plus largement possible et à participer activement à
l'avu les communautés de pratique de votre intérêt. Nous nous engageons à être en première
ligne de l'élaboration et le partage de ressources éducatives libres.
Les institutions suivantes ont participé au programme d'informatique appliquée : (1) Université
d'Abomey Calavi au Bénin ; (2) Université de Ougagadougou au Burkina Faso ; (3) l'Université
Lumière de Bujumbura au Burundi ; (4) l'Université de Douala au Cameroun ; (5) Université
de Nouakchott en Mauritanie ; (6) l'Université Gaston Berger au Sénégal ; (7) Université
des Sciences, des Techniques et technologies de Bamako au Mali (8) Ghana Institute of
Management and Public Administration ; (9) Université des Sciences et Technologies de
Kwame Nkrumah au Ghana ; (10) l'Université Kenyatta au Kenya ; (11) l'Université d'Egerton au
Kenya ; (12) l'Université d'Addis Abeba en Ethiopie (13) Université du Rwanda (14) ; Université
de Dar es Salaam en Tanzanie ; (15) l'Université Abdou Moumouni de Niamey au Niger ; (16)
l'Université Cheikh Anta Diop de Sénégal ; (17) Universidade Pedagógica au Mozambique ; et
(18) l'Université de la Gambie en Gambie.
Bakary Diallo,
Recteur de l'
2
Crédits de production
Auteur
Bouna Mohamed El Hacen
Pair Réviseur
Coordinateur du module
Jules Degila
Concepteurs pédagogiques
Elizabeth Mbasu
Benta Ochola
Diana Tuel
Equipe Média
Sidney McGregor Michal Abigael Koyier
3
Conception et Analyse d’algorithmes
Droits d’auteur
Ce document est publié dans les conditions de la Creative Commons
Http://fr.wikipedia.org/wiki/Creative_Commons
Attribution http://creativecommons.org/licenses/by/2.5/
Le gabarit est copyright African Virtual University sous licence Creative Commons Attribution-
ShareAlike 4.0 International License. CC-BY, SA
Supporté par
4
Table des matières
Avant propos 2
Crédits de production 3
Droits d’auteur 4
Supporté par 4
Aperçu du cours 8
Prérequis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Matériaux. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Objectifs du cours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Unités. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Introduction à l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Objectifs de l’unité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Termes clés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Évaluation de l’unité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Directives 14
Système de notation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Correction 15
Objectifs de l’unité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Termes clés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Activités d’apprentissage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5
Conception et Analyse d’algorithmes
Introduction 20
Expression de la complexité 20
Exemples de complexités 21
Détermination de la complexité 22
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Introduction 29
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Correction 33
Résumé de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Évaluation de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Directives 34
Introduction à l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Objectifs de l'unité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Termes clés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Activités d’apprentissage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Introduction 36
Le principe glouton 36
Stratégie 36
Algorithme 37
Eléments de l’algorithme 37
Correction 39
Évaluation de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
6
Activité 2: Diviser pour régner . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Introduction 41
Principe 41
Master-Théorème 43
Exemples : 44
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Correction 47
Introduction 49
Principe 49
Résumé de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Évaluation de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Directives 50
Correction 50
Objectifs de l’unité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Termes clés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Activités d’apprentissage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Activité 1: Arbres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Introduction 53
Définition 53
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5
Conception et Analyse d’algorithmes
Présentation 63
Parcours de graphes 64
Correction. 69
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Introduction 70
Correction 75
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Résumé de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Évaluation de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Directives 76
Correction 77
Introduction à l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Objectifs de l’unité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Termes clés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Activités d’apprentissage. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Introduction 80
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Correction 84
Présentation 84
Évaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Correction 86
Introduction 88
Résumé de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Évaluation de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
6
Directives 90
Réponses 90
Résumé de l’unité. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Évaluation du cours. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
Correction 94
Correction 96
7
Conception et Analyse d’algorithmes
Aperçu du cours
Bienvenue au cours Conception et Analyse d’algorithmes
Ce cours a pour but de donner aux étudiants quelques-unes des techniques avancées de
conception et d’analyse d’algorithmes. Ainsi, tous les grands thèmes de l’algorithme seront
abordés dans le cours : récursivité, Complexité temporelle et spatiale d’un algorithme,
programmation linéaire, NP-complétude, programmation dynamique, algorithmes
probabilistes, algorithmes d’approximation, etc.
Prérequis
Matériaux
Les matériaux nécessaires pour compléter ce cours comprennent les :
Objectifs du cours
À la fin de ce cours, l’étudiant devrait être en mesure de:
8
Aperçu du cours
• connaître les structures de données avancées telles que les arbres de recherche
binaires, graphes;
• Appliquer les structures de données pour mettre en œuvre des algorithmes de
graphe fondamentaux de manière efficace;
• Utiliser des algorithmes et structures de données avancés pour résoudre des
problèmes de la vie réelle
• Comparer et mettre en opposition les coûts et avantages de la structure
dynamique et statique des données en termes de performances
• Sélectionner les algorithmes sur la base de leurs performances (complexité)
• évaluer la complexité des solutions retenues ;
Unités
Unité 0: Connaissances de base
Cette unité porte sur l’évaluation des connaissances de l’étudiant à l’entrée du module. Il
doit répondre à une série de questions relatives au contenu de ce module. Ce test visant à
connaître le niveau de préparation pour affronter les différents concepts du cours.
Cette unité s’articule aux méthodes de conception d’algorithmes : glouton, diviser pour régner,
programmation dynamique, exploration, etc.
Cette unité porte sur les algorithmes d’arbres et des graphes : plus courts chemins, arbres
recouvrants de poids minimal, ….etc.
Cette unité étudie les Files de priorité, les Arbres binaires de recherche et les ensembles
disjoints
9
Conception et Analyse d’algorithmes
Évaluation
Les évaluations formatives (vérification de progrès) sont incluses dans chaque unité.Les
évaluations sommatives (tests et travaux finaux) sont fournies à la fin de chaque module et
traitent des connaissances et compétences du module.
Les évaluations sommatives sont gérées à la discrétion de l’établissement qui offre le cours. Le
plan d’évaluation proposé est le suivant:
Plan
Etude d’exemples
Estimation asymptotique
Programmation dynamique
Ensembles disjoints
10
Aperçu du cours
Unité 0
Unité 1
Unité 2
11
Conception et Analyse d’algorithmes
Unité 3
Unité 4
12
Unité 0. Évaluation diagnostique
Cette unité servira à préparer l’étudiant à une étude plus approfondie de la conception et
analyse d’algorithme.
Objectifs de l’unité
À la fin de cette unité, vous devriez être capable de:
Termes clés
Algorithme: Suites d’opérations élémentaires selon un
processus défini aboutissant à une solution.
13
Conception et Analyse d’algorithmes
Évaluation de l’unité
Test
Directives
Réponse aux questions l’évaluation dure une heure.
Ecrire un programme qui permet de saisir un tableau d’entiers de taille N et qui l’affiche de
telle sorte que tous les entiers pairs se retrouvent avant les entiers impairs.
Ecrire une procédure ou fonction permettant d’entrer deux valeurs M et N et d’afficher toutes
les valeurs paires entre M et N si M < N.
Système de notation
Le barème est indiqué à la fin de chaque question.
14
Unité 0. Évaluation diagnostique
Évaluation
Correction
Exercice 1
#include <stdio.h>
#include <stdlib.h>
short indice;
return 1;
return factorielle;
int main(void)
int nombre_lu;
printf(«erreur de saisie\n»);
exit(1);
return 0;
15
Conception et Analyse d’algorithmes
Exercice 2
#include <stdlib.h>
#include <studio.h>
#define N 4
int main() {
int tab[N];
int i ;
/∗ lecture ∗/
for (i = 0; i < N; i = i + 1) {
if(tab[i]%2 != 0) {
16
Unité 0. Évaluation diagnostique
Ecrire une fonction qui calcule la somme des éléments d’un tableau.
Ecrire une fonction qui inverse un tableau : le premier élément est permuté avec le
dernier, le deuxième avec l’avant dernier, etc.
int n, * ad1;
* ad1 = 3;
Exercice 3
Procedure calcul ;
Si M ≥ N Alors
Sinon
Debut
Si M mod 2 = 0 Alors
Ecrire (M)
FinSi ;
M + 1<- M
Fin
FinTantque
FinSi
Fin ;
17
Conception et Analyse d’algorithmes
18
Unité 1. Complexité des algorithmes
Quelle est l’utilité d’un programme qui donne un résultat au bout d’une semaine ? Il y a alors
une nécessité d’évaluer la performance d’un algorithme avant de le programmer.
Objectifs de l’unité
À la fin de cette unité, vous devriez être capable de:
Termes clés
Complexité algorithmique : Elle est donnée par un
ordre de grandeur théorique du temps de calcul et/ou
de l’espace mémoire utilisé en fonction d’une mesure
des données.
19
Conception et Analyse d’algorithmes
Activités d’apprentissage
Introduction
Un algorithme doit résoudre un problème de manière efficace, c’est-à-dire : rapide (en termes
de temps d’exécution) ; et économe en ressources (espace de stockage, mémoire utilisée).
Dans cette unité, on va présenter des outils qui nous permettront d’évaluer la qualité théorique
des algorithmes proposées.
Expression de la complexité
Les opérations élémentaires comprennent les évaluations d’expressions, les affectations, et
plus généralement tous les traitements en temps constant ou indépendant de l’algorithme
(entrées-sorties, . . . . Le détail de l’exécution de ces opérations au niveau du processeur par
l’intermédiaire d’instructions machine donnerait des résultats identiques à un facteur constant
près.
Soit m la machine, il existe des constantes m et M telles que pour tout algorithme A et pour
toute donnée d fournie en entrée de l’algorithme, si l’on note T(d) le nombre d’opérations
élémentaires effectuées par l’algorithme avec la donnée d en entrée et T_(m ) (d) le temps de
calcul du programme implémentant A avec la donnée d en entrée,
20
Unité 1. Complexité des algorithmes
mT(d)≤T_(m ) (d)≤MT(d)
T=θ(T_m )
On peut donc définir la complexité en temps d’un algorithme comme le nombre d’opérations
élémentaires T(n) effectuées lors de son exécution sur des données de taille n. Il s’agit donc
d’une fonction.
On distingue
la complexité dans le pire des cas (worst case complexity) : T_(pire ) (d) est le nombre maximal
d’opérations calculé sur toutes les données de taille n ;
la complexité dans le meilleur des cas (best case complexity) : T_(min ) (d) est le nombre
minimal d’opérations calculé sur toutes les données de taille n ;
Analyser un algorithme consiste à évaluer la ou les fonctions de complexité qui lui sont
associées. En pratique, on cherche à évaluer le comportement asymptotique de ces fonctions
relativement à la taille des entrées.
Exemples de complexités
en temps constant : T(n) = θ(1)
Voici un exemple d’une machine qui fait une opération élémentaire en 1µs (soit 106 opérations
par seconde), le tableau suivant montre les temps d’exécutions approximatifs de quelques
classes de problèmes en fonction de leurs tailles.
21
Conception et Analyse d’algorithmes
Nous notons que pour un algorithme, on considère uniquement les opérations fondamentales,
c’est à dire celles qui ont de l’influence sur la complexité :
Attention aux grands nombres : un petit nombre est un type prédéfini de taille connue ou
d’opérations élémentaires.
Détermination de la complexité
Dans l’espace
La taille est connue en fonction du type. Pour les ordres de grandeur, seuls les tableaux sont
pris en considération. La seule difficulté apparaît dans les allocations dynamiques (mémoire
demandée en cours d’exécution) ou dans les algorithmes récursifs, il faut compter le nombre
d’appels pour avoir une idée de la taille.
Dans le temps
• (1)
• Pour l’appel de fonction, il faut inclure la complexité de cette fonction dans la
complexité de la séquence.
• Alternative (Si…alors…sinon) : On prend toujours la complexité maximale. Sinon
on peut aussi faire une complexité moyenne mais il faut avoir des informations sur
le résultat moyen de la condition.
• Boucles : Complexité = (Complexité du corps de boucle) x (Nombre de tours).
• Algorithme récursif : Complexité = (Complexité de la fonction) x (nombre
d’appels).
22
Unité 1. Complexité des algorithmes
Conclusion
Évaluation
On considère deux manières de représenter ce que l’on appelle des « matrices creuses»,
c’est-à-dire des matrices d’entiers contenant environ 90% d’éléments nuls :
La complexité de la boucle est égale à la complexité du corps multipliée par le nombre de fois
qu’elle est répétée.
Démarche :
23
Conception et Analyse d’algorithmes
Structure conditionnelle
Pour la structure conditionnelle (si …. Sinon …) : on prend le maximum entre le alors et le sinon.
Procédures et fonctions: leur complexité est déterminée par celle de leur corps.
1.Algorithmes de tri
Il y a deux types fondamentaux d’opérations pour les algorithmes de tri : les comparaisons et
les transferts.
Tris simples
Ils sont faciles à mettre en œuvre mais leur complexité est mauvaise (O(N²)) et ne sont
utilisables que s’il y a peu de valeurs à trier (104 valeurs).
Sélection ordinaire
Idée : on cherche le minimum et on le met à la case 0, puis on cherche le minimum suivant que
l’on met à la case suivante et ainsi de suite. Cela correspond à l’algorithme suivant :
Début
posminçT[I]
Fin
Le fait que tout le tableau soit en entrée implique qu’il y a autant de transferts que de
comparaisons. On peut la trouver ainsi :
Nombre de transferts : 3 par boucle I, faite N-1 fois donc : 3N-3 soit une complexité
(N). C’est donc optimal.
Tri Bulle
On compare la première case avec la seconde. Si la case 1 est plus petite que la case 2, on
24
Unité 1. Complexité des algorithmes
Début
I<-0
Répéter :
Fini<-vrai
I<-I+1
Fin
2.Complexité :
Dans le meilleur des cas (tableau déjà trié) : on a N-1 comparaisons O(N) et 0 transferts O(1)
Dans le pire des cas (tableau trié à l’envers) on obtient N(N-1)/2 nombres de transferts et N(N-
1)/2 nombres de comparaisons. On a alors une complexité de O(N²) ; ce qui est très mauvais.
En moyenne : Le calcul d’une moyenne est trop compliqué. On admettra que la complexité
moyenne est de O(N²).
Insertion séquentielle
Element : Tinformations
Trouvé : booléen
Début :
{on cherche la position de T[i] entre 0 et i-1 de droite à gauche en décalant les plus grands}
Element <-T[i]
Pos<-i-1,
trouvé<-false
25
Conception et Analyse d’algorithmes
sinon trouvé<-vrai
T[pos+1]<-Element {transfert}
Fin
Fin
En moyenne : O(N²)
Remarque :
Il existe une amélioration à cet algorithme : en faisant une recherche de la position d’insertion
par dichotomie. La complexité du nombre de comparaisons est alors O(nlog n), ce qui est
optimal.
Lorsqu’on trie de gros objets, on ne peut pas éviter de les comparer mais on peut éviter de
les déplacer en créant un deuxième tableau contenant les indices de l’ordre du tri du premier
tableau.
Tris rapides
Généralement,
On constate qu’on trie des parties de tableau, il faut donc indiquer le début et la fin de la
portion à traiter : les paramètres seront donc T, début, fin.
Début
26
Unité 1. Complexité des algorithmes
Fin
En moyenne, cet algorithme est optimal : (nlogn) et au maximum la complexité pourrait être
O(N²)
• Un arbre parfait
• Tout nœud a une valeur et permet d’accéder à celle de tous ses descendants.
Les méthodes associés sont : estVide, minimum, insérer, supprimerMin
Principe :
entier n=tabATrier.length;
//on sélectionne un par un les minimums successifs du tas, qui sont mis à leur place dans le
tableau tabATrier[i]=unTas.minimum(); //O(1) pour chaque i
fait;fin
27
Conception et Analyse d’algorithmes
Conclusion
Tri par insertion excellent si liste initiale presque triée, et peut débuter sans liste initiale
complète
Évaluation
On considère, pour effectuer la recherche d’un élément dans un tableau, la recherche
séquentielle et la recherche dichotomique. On s’intéresse à leur complexité temporelle.
Pour cela, considérer un tableau ayant mille éléments (version trié, et version non trié).
2. Quels sont les cas où le tableau est parcouru complètement et les cas
où un parcours partiel est suffisant ?
28
Unité 1. Complexité des algorithmes
Introduction
En complexité, on ne prend en considération que des fonctions positives de N dans IR. On
ne veut pas évaluer de manière exacte les temps d’exécution (d’autant que ça dépend des
machines…). En réalité, le calcul de la complexité de manière exacte n’est pas raisonnable vu
la quantité d’instructions de la plupart des programmes ; de plus il n’est pas utile pour pouvoir
comparer deux algorithmes. On se contente en général de trouver des approximations.
Définitions
Notation grand-O
O(g)
et un rang n_0
Notation grand- Ω
Ω(g) constitue des fonctions positives f pour lesquelles il existe une constante strictement
positive α
et un rang n_0
pour tout n ≥ n0
Notation grand-θ
Ces fonctions croissent aussi vite que g (qui ont même ordre de grandeur).
Exemple
29
Conception et Analyse d’algorithmes
avec α > 0
même Θ(nlnn)
Interprétations
Si f et g sont des fonctions positives réelles : f(n) =O(g(n)) si et seulement si le rapport f/g est
borné à l’infini (on dit f est bornée par g). Figure 1.3.1 donne l’interprétation géométrique de
la notation O.
Interprétation de grand-Ω
alors g est une borne inférieure asymptotique pour f. La figure 1.3.2 donne une interprétation
géométrique de la notation Ω
30
Unité 1. Complexité des algorithmes
Interprétation de la notation θ:
implique que f et g ont le même ordre de grandeur. La figure 1.3.3 donne une interprétation
géométrique de la notation θ
Classes de complexité
Les algorithmes usuels peuvent être classés en un certain nombre de grandes classes de
complexité, On présente dans cette partie les classes de complexité courantes :
La classe constante O(1) : le temps d’exécution n’augmente pas quand le paramètre croit : par
exemple l’affectation, la comparaison.
La classe linaire O(n) : le temps d’exécution augmente linéairement quand le paramètre croit.
Par exemple somme des n premiers entiers ou parcours un ensemble de données.
La classe quasi linéaire O(n*log(n)) : augmentation un peu supérieure à O(n). Par exemple
algorithmes qui décomposent un problème en d’autres plus simples, traités indépendamment
et qui combinent les solutions partielles pour calculer la solution générale.
La classe quasi quadratique 〖O(n〗2) : le temps d’exécution est multiplié par quatre lorsque le
paramètre double. Par exemple parcourir un exemple de données en utilisant deux boucles
imbriquées.
La classe polynomiale : quand le paramètre double, le temps d’exécution est multiplié par 2i.
Par exemple parcourir un ensemble de données en utilisant deux boucles imbriquées.
31
Conception et Analyse d’algorithmes
La classe exponentielle : 〖O(i〗n) : quand le paramètre double, le temps d’exécution est élevé
à la puissance 2. Par exemple générer tous les sous-ensembles possibles d’un ensemble de
données.
Conclusion
On peut conclure que les algorithmes usuels peuvent être classés en un certain nombre de
grandes classes de complexité.
Évaluation
Soit les algorithmes suivants avec un temps d’exécution pour une longueur de données
n.
1. Algorithme A1 T(n) = 3n + 2
2. Algorithme A2 T(n) = 6
3. Algorithme A3 T(n) = 4n 2 + n + 2
4. Algorithme A4
Exécuter A1;
Exécuter A2;
Exécuter A3;
32
Unité 1. Complexité des algorithmes
5. Algorithme A5
pour i de 1 à n faire
Exécuter A3;
fin pour
Exécuter A1;
6. Algorithme A6
pour i de 1 à 5 faire
Exécuter A1;
fin pour
Correction
Résumé de l’unité
Cette unité a permis de comprendre l’utilité de l’évaluation de la performance d’un algorithme
avant de le programmer. La complexité d’un algorithme a été abordé afin de pouvoir
déterminer qu’un algorithme est optimal et de le comparer à un autre afin de déterminer
lequel est meilleur.
33
Conception et Analyse d’algorithmes
Évaluation de l’unité
Test
Directives
Les barèmes sont donnés à la suite de chaque question
34
Unité 2. Techniques de conception d’algorithmes
Objectifs de l'unité
À la fin de cette unité, vous devriez être capable de:
Termes clés
Paradigme : Un paradigme de programmation
Informatique désigne la manière d’analyser le monde
dans le but de concevoir un programme Informatique.
35
Conception et Analyse d’algorithmes
Activités d’apprentissage
Introduction
Les algorithmes pour problèmes d’optimisation exécutent en général une série d’étapes,
chaque étape proposant un ensemble de choix. Pour de nombreux problèmes d’optimisation,
la programmation dynamique est une approche bien trop lourde pour déterminer les meilleurs
choix ; d’autres algorithmes, plus simples et plus efficaces, peuvent faire l’affaire. Un algorithme
glouton fait toujours le choix qui lui semble le meilleur sur le moment.
Autrement dit, il fait un choix localement optimal dans l’espoir que ce choix mènera à une
solution globalement optimale. Cette activité étudie les problèmes d’optimisation qui peuvent
se résoudre par des algorithmes gloutons.
Le principe glouton
Un algorithme de glouton est un algorithme qui résout des problèmes d’optimisation (qui
optimise une fonction objectif), il cherche à construire une solution pas à pas
Stratégie
ajouter la plus grande pièce possible
36
Unité 2. Techniques de conception d’algorithmes
Algorithme
RENDRE-MONNAIE(P,n)
S←Ø
i←1
et i ≤ P.longueur faire
si n−P[i] ≥ 0 alors
n ← n−P[i]
S ← S∪{P[i]}
i ← i+1
si n = 0
retourner S
sinon
P = {8,4,2}: toujours une solution optimale si elle existe (si n est pair, n ≤ 14)
P = {5,2}* : solution existe toujours (si n ≥ 4), mais on ne la trouve pas toujours (n = 6)
P = {5,4,1}* : solution existe toujours, on la trouve toujours, mais elle n’est pas toujours
optimale (n = 8)
Eléments de l’algorithme
Tableau des candidats C (tableau des pièces disponibles)
37
Conception et Analyse d’algorithmes
Stratégie
Algorithme général
GLOUTON(C)
S←Ø
i←1
si REALISABLE(S∪{C[i]}
) alors
S ← S∪{C[i]}
i ← i+1
si SOLUTION(S)
retourner S
sinon
Complexité :
Conclusion
Cette activité vous a présenté les problèmes d’optimisation qui peuvent se résoudre en
utilisant les algorithmes gloutons.
38
Unité 2. Techniques de conception d’algorithmes
Évaluation de l’unité
Le problème du rendu de monnaie.
Comment rendre une somme donnée avec le minimum de pièces. Nous regarderons tout
d'abord notre système monétaire : des pièces de 1, 2, 5, 10, 50, 100, 200.
Correction
1. Pour rendre la monnaie sur 263 centimes d’euros, on rend une pièce de
200, de 50, de 10, de 2 et de 1.
rendu := 0
i := 0
i := i+1
sinon alors
39
Conception et Analyse d’algorithmes
r[i] := r[i] + 1
retourner r
pour s - c
4. Si les pièces ont comme valeurs 1,3,4, alors l’algorithme glouton va rendre
la monnaie sous la forme d’une pièce de 4 et de deux pièces de 1, alors
que rendre deux pièces de 3 aurait été optimal, il ne fournit donc pas la
solution optimale.
, on a donc p ≤ q
qui est au moins aussi loin que y1, intuitivement, on déduit que gk est
au moins aussi loin que yk
40
Unité 2. Techniques de conception d’algorithmes
Introduction
La méthode de diviser pour régner est une méthode qui permet, parfois de trouver des
solutions efficaces à des problèmes algorithmiques. L’idée est de découper le problème initial,
de taille n, en sous-problèmes de taille plus petite, résoudre les sous-problèmes récursivement
(ou les résoudre directement si de taille suffisamment petite), puis recombiner les solutions des
sous-problèmes pour obtenir la solution du problème d’origine.
Principe
Le paradigme diviser-pour-régner implique trois étapes à chaque niveau de la récursivité :
Algorithme naïf
MULTIPLIER-MATRICES(A, B)
Soit n
Pour i ← 1 à n faire
Pour j ← 1 à n faire
cij ← 0
Pour k ← 1 à n faire
retourne C
41
Conception et Analyse d’algorithmes
(r s t u )=(a b c d )(e f g h )
r = ae+b f ;
s = ag+bh;
t = ce+df
u = cg+dh:
À partir de ces équations on peut aisément dériver un algorithme « diviser pour régner » dont
la complexité est donnée par la récurrence :
étant en θ(n^2).
À partir du temps d’exécution pour des entrées de taille moindre. On peut alors se
servir d’outils mathématiques pour résoudre la récurrence et trouver des bornes pour les
performances de l’algorithme.
Une récurrence pour le temps d’exécution d’un algorithme diviser-pour-régner s’appuie sur les
trois étapes du paradigme de base. Comme précédemment, soit T(n) le temps d’exécution
d’un problème de taille n
pour une certaine constante c, la solution directe prend un temps constant que l’on écrit θ(1).
42
Unité 2. Techniques de conception d’algorithmes
pour construire la solution finale à partir des solutions aux sous-problèmes, la relation de
récurrence prend alors la forme :
Master-Théorème
On considère un problème de taille n, qu’on découpe en a sous-problèmes de taille n/b
permettant de résoudre le problème.
Soient a ≥ 1
et b >
Alors T(n)
Si f(n)= θ(n^(logb a)
Si f(n) = Ω(n^(logba-ε)
, et si af(n/b)≤cf(n)
43
Conception et Analyse d’algorithmes
Exemples :
Algorithme tri par fusion
Diviser : Diviser la suite de n éléments à trier en deux sous-suites de n/2 éléments chacune.
Régner : Trier les deux sous-suites de manière récursive en utilisant le tri par fusion.
Combiner : Fusionner les deux sous-suites triées pour produire la réponse triée.
procedure TriFusion(T)
if n ≤ 1 then
return T
else
n = |T|
T1 = TriFusion(T[0 . . . n/2])
return Fusion(T1,T2)
end if
end procedure
La complexité T(n)
T(0)= 0,
T(1)= 0,
T(n) ≈ 2 T(n/2) + n - 1
Dichotomie
Cet algorithme fait partie des méthodes diviser pour régner. Elle consiste pour un tableau de
taille n à exécuter un algorithme de façon à réduire le problème à un tableau de taille n/2. On
répète alors l'algorithme de réduction sur ce dernier tableau. Ainsi, il suffit de connaitre la
résolution pour un problème de taille faible (typiquement n=1 ou n=2) pour obtenir la totalité
de la résolution. Ce type d'algorithme est souvent implémenté de manière récursive. Lorsque
cette technique est utilisable, elle conduit à un algorithme très efficace et très lisible.
44
Unité 2. Techniques de conception d’algorithmes
Soit T est un tableau trié de taille n, on s’intéresse à l’algorithme qui recherche si x est un
élément de T au moyen d’une dichotomie. Pour l’algorithme récursif, on spécifie un indice de
début d et de fin f, et on recherche si x est dans T entre les positions d et f. L’appel initial se
fait avec d = 0 et f = n − 1.
Algorithme Dichotomie
procedure Recherche(T,x,d,f)
if f < d then
return Faux
else
m = b b+a 2 c
if T[m] = x then
return Vrai
else
return Recherche(T,x,d,m − 1)
end if
end if
end procedure
a=1
car on appelle soit à gauche, soit à droite (ou on a fini, mais on se place dans le pire des cas),
b=2
d=0
45
Conception et Analyse d’algorithmes
Conclusion
On a vu dans cette activité une technique de conception d’algorithmes : diviser pour régner.
On a donné le Master-Théorème qui permet d’obtenir des bornes asymptotiques sur la plupart
des fonctions rencontrées lors de l’analyse de coût des algorithmes Diviser pour Régner.
Évaluation
Exercice 1 – Valeur encadrée
Exemple Soit le tableau A[1..5] = [3, 7, 8, 43, 556] et les bornes a = 40, b = 50. Dans ce
cas-là la valeur encadrée existe : c’est A[4] = 43.
2. Analyser sa complexité
Exercice 2
Le but de cet exercice est de choisir l’algorithme de type diviser pour régner le plus rapide
pour un même problème.
en temps constant.
46
Unité 2. Techniques de conception d’algorithmes
Correction
Exercice 1
1. Coupons le tableau en deux moitiés : A[s..m] et A[m + 1..f]. Les trois cas
ci-dessous correspondent à trois positions de l’élément de milieu A[m] par
rapport à l’intervalle [a, b].
Dedans :a ≤ A[m] ≤ b
.On a déjà trouvé une valeur encadrée A[m]. On retourne son indice.
fonction chercher(s,f)
// cas de base
si (s=f)
retourner s
sinon retourner ⊥
m=(s+f)/2
si A[m] < a
ind= chercher(m+1,f)
sinon si a ≤A[m] ≤b
ind=m
sinon
ind=chercher(s,m)
retourner ind
47
Conception et Analyse d’algorithmes
Exercice 2
Question 1
T(n)= 2 T (n/2)+n^(2 )
Question 1a
a = 4, b = 2, f(n) = O(√n),
cas 1. ε=3/2
Question 1b
Question 2
a = 1, b = 2, f(n)=Ω(n^(1/2)),
Question 2a
a=b=2, T(n)=θ(1),
cas 1. ε=1
, ce implique T(n)=θ(n).
Question 2b
48
Unité 2. Techniques de conception d’algorithmes
Introduction
La programmation dynamique, comme la méthode diviser-pour-régner, résout des problèmes
en combinant des solutions de sous-problèmes. (le mot « Programmation », dans ce contexte,
fait référence à une méthode tabulaire et non à l’écriture de code informatique.). Comme nous
l’avons vu à l’activité 2.2, les algorithmes diviser-pour-régner partitionnent le problème en
sous-problèmes indépendants qu’ils résolvent récursivement, puis combinent leurs solutions
pour résoudre le problème initial. La programmation, quant à elle, peut s’appliquer même
lorsque les sous-problèmes ne sont pas indépendants, c’est-à-dire lorsque des sous-problèmes
ont des sous-sous-problèmes communs. Dans ce cas, un algorithme diviser-pour-régner fait
plus de travail que nécessaire, en résolvant plusieurs fois le sous-sous-problème commun. Un
algorithme de programmation dynamique résout chaque sous-sous-problème une seule fois et
mémorise sa réponse dans un tableau, évitant ainsi le recalcul de la solution chaque fois que le
sous-sous-problème est rencontré.
Lorsque les sous-problèmes ne sont pas indépendants (c’est-à-dire lorsque les sous-problèmes
ont des sous-sous-problèmes communs) la programmation récursive se révèle le plus souvent
très inefficace car elle conduit à résoudre de nombreuses fois les sous-sous-problèmes
communs.
Principe
Afin de résoudre un problème, on commence tout d’abord par résoudre les plus petits sous-
problèmes et on stocke les valeurs de ces sous-problèmes dans une table de programmation
dynamique. Ensuite, on utilise ces valeurs pour calculer la valeur des sous-problèmes de plus
en plus grands, jusqu’à obtenir la solution de notre problème global.
Résumé de l’unité
Dans cette unité, vous avez étudié les structures de données de base telles que les listes,
les piles et les files, et découvert l’importance de ces structures à travers des exemples
d’application à travers les algorithmes glouton, diviser-pour-règner et la programmation
dynamique.
49
Conception et Analyse d’algorithmes
Évaluation de l’unité
Vérifiez votre compréhension!
Directives
Répondre aux questions de l’exercice suivant.
Exercice 1
Le professeur Bell conduit une voiture entre Amsterdam et Lisbonne sur l’autoroute E10.
Son réservoir, quand il est plein, contient assez d’essence pour faire n kilomètres, et sa
carte lui donne les distances entre les stations-service sur la route.
Correction
on a donc p ≥ q
Ici les deux suites sont bien sûr des suites de stations-service, triées
de celle la plus proche du point de départ à celle la plus éloignée. Soit
k le plus petit entier tel que : ∀i < k,xi = yi
, et xk ≠yk.
50
Unité 2. Techniques de conception d’algorithmes
. G^'
est une liste de même taille. Montrons que c’est aussi une solution —et
donc une solution optimale. Il nous faut vérifier qu’il n’y a pas de risque
de panne sèche c’est-`a-dire que :
– x_k -y_(k-1) ≤ n.
– y_(k+1) - 〖x 〗_k≤ n.
de G^'
G^'
. Alors p ≤ q
51
Conception et Analyse d’algorithmes
Après une description générale des arbres, nous attaquerons les graphes et leurs algorithmes.
Objectifs de l’unité
À la fin de cette unité, vous devriez être capable de:
Termes clés
Arbre binaire de recherche : une structure de données
qui peut supporter des opérations courantes sur des
ensembles dynamiques.
52
Unité 3. Structure de données dynamiques
Activités d’apprentissage
Activité 1: Arbres
Introduction
Un arbre est une structure de données récursive générale, représentant un arbre au sens
mathématique. C’est un cas particulier de graphe qui n’a qu’une seule source et aucun cycle.
Les répertoires sur la plupart des systèmes d’exploitation actuels forment un arbre, on peut
distinguer :
On commence par décrire les opérations de base sur les arbres binaires, et on exprime ensuite
d’autres opérations à l’aide de ces opérations de base.
Définition
Un arbre est une structure de donnée avancée qui généralise la liste. Dans un arbre, une cellule
peut avoir plusieurs successeurs, au contraire de la liste qui possède un seul successeur pour
la cellule. On parle de nœud (au lieu de cellule). Un nœud père peut avoir plusieurs nœuds
fils. Un fils n’a qu’un seul père, et tous les nœuds ont un ancêtre commun appelé la racine de
l’arbre. La figure 3.1.1 illustre un exemple d’un arbre.
les éléments restants sont partitionnés en m ≥ 0 ensembles disjoints T1, T2,…,Tm qui sont
eux-mêmes des arbres (ce sont les sous-arbres issus de la racine).
53
Conception et Analyse d’algorithmes
Le nombre de nœuds est défini de manière récursive en arbre de moins de m nœuds, ce qui
permet d’éviter le problème de circularité. Chaque nœud est défini par son étiquette et ses
sous-arbres.
Terminologie
On utilise pour les arbres une terminologie inspirée des liens de parenté, comme montré dans
la figure 3.1.2 :
54
Unité 3. Structure de données dynamiques
Autres représentations
Un arbre binaire est un arbre avec une racine, et où chacun des nœuds possède :
La Figure 3.1.4 montre un exemple qui illustre un arbre binaire, dessiné avec sa racine en haut
et ses branches en descente, à l’inverse d’un arbre dans la nature :
55
Conception et Analyse d’algorithmes
Un arbre binaire peut aussi être réduit à l’arbre vide. Pour comprendre l’importance de l’arbre
vide, voici comment on peut donner une définition récursive tout à fait cohérente d’un arbre
binaire : il s’agit soit de l’arbre vide, soit d’un nœud racine auquel sont accrochés un arbre à
gauche et un arbre à droite aussi. Si l’on oubliait le cas de l’arbre vide, la définition perdrait
toute signification : notamment l’arbre ne pourrait avoir aucune feuille, c’est-à-dire un nœud
auxquels sont accrochés deux arbres vides.
On peut aussi utiliser les fonctions suivantes pour modifier les champs d’un nœud interne :
struct node
56
Unité 3. Structure de données dynamiques
TElement value;
tree left;
tree right;
};
On remplacera le type TElement par type ou la structure de données que l’on veut utiliser
comme entité significative des nœuds de l’arbre.
D’autre part, on peut remarquer que l’arbre vide sera représenté par la constante NULL (voir la
figure 3.1.5 : un arbre binaire).
Dans le premier cas, nous pouvons utiliser un tableau pour stocker les fils. Ainsi pour un arbre
d’arité 4 nous aurons l’implémentation suivante :
struct node
TElement value;
tree child[4];
};
57
Conception et Analyse d’algorithmes
La deuxième solution consiste à utiliser une liste chainée pour la liste des fils.
struct cell{
tree son;
list next;
};
struct node{
TElement value;
list child;
};
Info *info;
} *Arbre, Noeud;
Arbre a = NULL;
58
Unité 3. Structure de données dynamiques
Arbre filsGauche(Arbre a)
return res;
début
insertionG := a;
fin
Feuille
variables
début
estFeuille := res;
fin
variables
début
hauteur := res ;
fin
59
Conception et Analyse d’algorithmes
variables
début
si v = info(a) alors
finsi
finsi
finsi
supparbre := res ;
fin
Parcours en profondeur
60
Unité 3. Structure de données dynamiques
Celui-ci représente un seul parcours en profondeur de l’arbre. Il s’agit d’un parcours d’arbre en
profondeur à gauche d’abord et préfixe.
Les types de parcours infixe, suffixe et post-fixe sont les plus importants, en effet chacun à
son application particulière. Nous Commençons par le parcours préfixe, celui-ci traite la racine
d’abord.
traiter_racine(T);
parcours_prof_prefixe(FilsGauche(T));
parcours_prof_prefixe(FilsDroit(T));
fin si
La fonction (ou procédure) traiter_racine, est une fonction que vous définissez vous même, il
s’agit par exemple d’une fonction d’affichage de l’élément qui est à la racine.
parcours_prof_infixe(FilsGauche(T));
traiter_racine(T);
parcours_prof_infixe(FilsDroit(T));
fin si
parcours_prof_suffixe(FilsGauche(T));
parcours_prof_suffixe(FilsDroit(T));
traiter_racine(T);
fin si
Conclusion
Dans cette activité, on a étudié les arbres en général et les arbres binaires en
particulier. D’après l’étude qu’on a faite sur les algorithmes itératifs du parcours en profondeur
dans un arbre binaire on peut déceler les problèmes qui y sont liés. Pour aboutir à l’algorithme
61
Conception et Analyse d’algorithmes
proprement dit pour chacun des différents parcours en profondeur, nous retenons qu’il faut
procéder par deux phases qui sont l’empilement et le dépilement. Par ailleurs cette étude
nous a aussi permis de nous familiariser à la résolution de problèmes formalisés de façon
récursive avec des procédés itératifs
Évaluation
Voici une liste aléatoire de 15 éléments. Notez que vous pouvez faire cet exercice en
prenant une autre liste aléatoire ; évidemment, il y a peu de chances que vous obteniez le
même résultat.
25 60 35 10 5 20 65 45 70 40 50 55 30 15
Correction
1. Un arbre binaire de recherche est tel que tout nœud a une clé supérieure
à celles des nœuds de son sous arbre gauche et inférieure à celles des
nœuds de son sous arbre droit. On peut encore dire que la clé d’un nœud
est comprise entre la plus grande clé de son sous arbre gauche et la plus
petite clé de son sous arbre droit.
3. 25 est introduit dans un arbre vide. 60 étant plus grand que 25 est mis
à droite de 25. 35 étant plus grand que 25 et plus petit que 60 est mis à
gauche de 60. 10 est plus petit que 25 est mis à gauche de 25. 5 est plus
petit que 25 et plus petit que 10, il est mis à gauche de 10. 20 est plus
petit que 25 et plus grand que 10, il est mis à droite de 10. 65 est plus
grand que 25 et plus grand que 60, il est mis à droite de 60. 45 est plus
grand que 25, plus petit que 60 et plus grand que 35, il est mis à droite
62
Unité 3. Structure de données dynamiques
de 35. 70 est plus grand que 25, plus grand que 60 et plus grand que 65.
Il est mis à droite de 65. 40 est plus grand que 25, plus petit que 60, plus
grand que 35 et plus petit que 45, il est mis à gauche de 45. 50 est plus
grand que 25, plus petit que 60, plus grand que 35 et plus grand que 45,
il est mis à droite de 45. 55 est plus grand que 25, plus petit que 60, plus
grand que 35, plus grand que 45, plus grand que 50, il est mis à droite de
50. 30 est plus grand que 25, plus petit que 60 et plus petit que 35, il est
mis à gauche de 35. Enfin, 15 est plus petit que 25, plus grand que 10 et
plus petit que 20, il est mis à gauche de 20. On obtient l’arbre suivant.
Présentation
Le graphe est une structure de données très utilisées dans divers domaines par exemple :
Cette structure permet de représenter des relations entre éléments. Un graphe est constitué
d’un ensemble S de sommets mis en relation par un ensemble A d’arêtes ou arcs, couples
d’éléments de S.
63
Conception et Analyse d’algorithmes
Les graphes non-orientés où la directionnalité de l’arête n’intervient pas : ainsi si (i,j) ∈ A alors
(j,i) ∈ A.
• Les arbres qui constituent des graphes particuliers avec définition d’un sommet
racine : tout sommet de l’arbre ne peut alors être atteint que par un chemin
unique depuis la racine.
• Les graphes acycliques qui ne comportent aucun cycle (un graphe comporte un
cycle lorsqu’il est possible de trouver un chemin arbitrairement long entre deux
sommets de celui-ci).
• Les automates qui représentent des graphes dont les arêtes sont étiquetées avec
définition d’une liste d’états initiaux et d’états terminaux.
• Les graphes d’arêtes évaluées où l’on associe à chaque arête une valeur.
Nous nous intéressons ici à la structure générale de graphe (non-orienté et
non-acyclique).
La figure 3.2.1 montre un graphe G orienté d’ordre 5. Il y a une boucle sur les sommets B et E.
Parcours de graphes
Parcours en largeur
couleur(s) ← GRIS
d(s) ← 0
pere(s) ← NIL
F ← {s}
couleur(v) ← BLANC
d(v) ← ∞
pere(v) ← NIL
fin pour
64
Unité 3. Structure de données dynamiques
v ← tete(F)
couleur(w) ← GRIS
d(w) ← d(v) + 1
pere(w) ← v
Enfiler(F, w)
fin si
fin pour
Defiler(F)
couleur(v) ← NOIR
Parcours en profondeur
On présente ici l’algorithme de parcours en profondeur PP(G, s). Cet algorithme se décrit
naturellement de manière récursive.
couleur(v) ← BLANC
pere(v) ← NIL
fin pour
temps ← 0
VisiterPP(v)
fin si
fin pour
Algorithme VisiterPP(v) :
couleur(v) ← GRIS
65
Conception et Analyse d’algorithmes
pere(w) ← v
VisiterPP(w)
fin si
fin pour
couleur(v) ← NOIR
Le tri topologique
Le tri topologique d’un graphe orienté acyclique G = (V,E) sert à ordonner tous les sommets de
sorte que si
est un arc de
alors
apparaît avant
dans le tri. Cette notion est fréquente dans de nombreux problèmes d’ordonnancement :
chaque sommet représente une tâche à effectuer, et les arcs indiquent celles de ces tâches qui
doivent être réalisées avant une autre tâche.
début
L ← liste-vide ;
retour (L) ;
fin
début
66
Unité 3. Structure de données dynamiques
Ajouter s en tête de L ;
fin
Voici l’algorithme correspondant:
Calculer G^(-1)
Exécuter PP(G^(-1))
.On cherche donc un sous-graphe T = (X, F) connexe dont la somme des poids des arêtes est
minimale.
Algorithme de Kruskal
Cet algorithme est basé sur la caractérisation des arbres comme des graphes acycliques
maximaux au sens de l’inclusion.
Algorithme (G, w):
composante(v) ← {v}
fin pour
i←1
67
Conception et Analyse d’algorithmes
E(T) ← {}
UNIFIER(composante(u), composante(v))
fin si
i←i+1
retourner E(T)
Algorithme de Prim
Algorithme (G, w)
cle(v) ← ∞
fin pour
cle(r) ← 0
pere(r) ← NIL
tant que F
∅ faire
u ← EXTRAIRE MIN(F)
pere(v) ← u
cle(v) ← w(u, v)
fin si
fin pour
68
Unité 3. Structure de données dynamiques
Conclusion
Dans cette activité on a présenté les principaux algorithmes de graphes (les algorithmes
courants de la théorie des graphes). L’algorithme de Prim maintient une composante connexe.
L’algorithme de Kruskal maintient l’absence de cycle.
Évaluation
Pour le graphe pondéré donné dans la figure 3.2.2, on cherche à trouver l’arbre couvrant
minimum en appliquant un algorithme du cours.
Figure 3.2.2
1. Choisissez un algorithme (écrivez juste son nom s’il s’agit d’un algorithme
connu).
Correction.
On part du sommet 0.
69
Conception et Analyse d’algorithmes
Introduction
Le problème du plus court chemin consiste à déterminer le chemin de coût minimum reliant un
nœud
à un nœud
. Nous allons présenter, dans cette activité, les algorithmes les plus utilisées pour résoudre ce
problème notamment l’algorithme de DIJKSTRA et l’algorithme de BELLMAN – FORD.
L’algorithme de DIJKSTRA est le plus utilisé car il est simple à mettre en œuvre, efficace en
temps d’exécution et bien adapté aux situations courantes.
Dijkstra : Cet algorithme sert à résoudre le problème du plus court chemin. Il permet,
par exemple, de déterminer un plus court chemin pour se rendre d’une ville à une autre
connaissant le réseau routier d’une région.
Algorithme Dijkstra(G, w, s)
d(v) ← ∞
pere(v) ← NIL
couleur(v) ← BLANC
fin pour
d(s) ← 0
F ← FILE PRIORITE({s}, d)
70
Unité 3. Structure de données dynamiques
si d(v) = ∞ alors
INSERER(F, v)
fin si
pere[v] ← pivot
fin si
fin si
fin pour
couleur[pivot] ← NOIR
Bellman : Cet algorithme calcule les plus courts chemins depuis un sommet source donné dans
un graphe orienté pondéré.
Notons :
w : E(G) → R
s : source de G
Algorithme : Bellman-court(G;w; s)
TriTopologique(G)
pour i de 1 à n − 1 faire
d[vi ] ← ∞
pere[vi ] ← NIL
fin pour
d[v1] ← 0
pour i de 1 à n − 1 faire
pere[u] ← vi
71
Conception et Analyse d’algorithmes
fin si
fin pour
fin pour
Algorithme de Ford est un algorithme qui calcule des plus courts chemins depuis un sommet
source donné dans un graphe orienté pondéré.
G : graphe orienté
w : E(G) → R
s : source de G
Algorithme Ford(G, w, s)
d[v] ← ∞
pere[v] ← NIL
fin pour
d[s] ← 0
pour i de 1 à n − 1 faire
pere[v] ← u]
fin si
fin pour
fin pour
retourner FAUX
fin si
fin pour
retourner VRAI
On souhaite par exemple trouver le trafic maximal entre deux villes d’un réseau routier dont on
connait la capacité (le nombre de voiture par heure sur chaque tronçon).
72
Unité 3. Structure de données dynamiques
Comment trouver un flot dont la valeur est maximale pour un graphe valué qui a une seule
source et un seul puits ?
Flots
c : E(G) → R+
s : source de G
t : puits de G
La valeur du flot sur cet arc sera la valeur du flot de s à t. On note respectivement par I(e) et
T(e) l’extrémité initiale et l’extrémité terminale d’un arc e.
Algorithme FlotMax(G, c, s, t)
f[e] ← 0
fin pour
répéter
Marquage(G, c, f, s, t)
si t ∈ Y alors
v←t
C+ ← {(t, s)}
e ← A[v]
73
Conception et Analyse d’algorithmes
si v = T[e] alors
C + ← C + ∪ {e}
v ← I[e]
sinon
C− ← C− ∪ {e}
v ← T[e]
fin si
fin si
fin pour
fin pour
jusqu’ à t ∈
Conclusion
On peut conclure que la difficulté principale de l’algorithme de Kruskal est une implémentation
efficace des sous-ensembles de l’ensemble des sommets. Plus précisément, il faut pouvoir
trouver le sous-ensemble auquel appartient un sommet donné ;
Le temps d’exécution est très dépendant de la façon dont cette implémentation est réalisée.
74
Unité 3. Structure de données dynamiques
Évaluation
On considère le graphe orienté ci-dessous valué par des longueurs d’arcs. On cherche à
déterminer les plus courts chemins de à tout autre sommet. Dire pourquoi on peut utiliser
pour cela l’algorithme de Bellman.
Correction
On peut appliquer l’algorithme de Bellman parce que le graphe est sans circuit, ce qu’on peut
vérifier en effectuant la numérotation topologique qui a été faite ci-dessous. Les numéros
topologiques sont encadrés.
Les distances sont indiquées en gras à côté des sommets et les plus courts chemins sont
indiqués par les arcs en gras.
75
Conception et Analyse d’algorithmes
Résumé de l’unité
Les principales structures de données avancées ont été présentées (arbres, graphes) en
précisant à chaque fois leurs mémorisations, les algorithmes de parcours, de création et de
désallocation, plus des algorithmes spécifiques à chaque structure de données.
Évaluation de l’unité
Test
Directives
Les barèmes sont fixés devant chaque question
76
Unité 3. Structure de données dynamiques
3. (3 points) Est-ce que cet arbre est un arbre entier, un arbre parfait
(=complet), et/ou un arbre dégénéré ?
4. (2.5 points) Afficher cet arbre binaire de la manière préfix, puis infix, et
ensuite postfix. Premièrement, on va afficher cet arbre sans utiliser des
parenthèses.
Correction
1.
3. Cet arbre est entier car chaque nœud a zéro ou deux fils. Par contre, cet
arbre est ni parfait ni dégénéré.
Préfix * + 3 / 4 2 - 8 * 2 3
Infix 3 + 4 / 2 * 8 - 2 * 3
Postfix 3 4 2 / + 8 2 3 * - *
Préfix *( +( 3, /( 4, 2) ) , -( 8, *( 2, 3) ) )
77
Conception et Analyse d’algorithmes
78
Unité 4. Structures de données spécialisées
Objectifs de l’unité
À la fin de cette unité, vous devriez être capable de:
• Comprendre les structures de données avancées telles que les arbres binaires,
les ensembles disjoints
• Implantation des ensembles disjoints, composantes connexes.
Termes clés
File de priorité : Une file de priorité est un objet
contenant des éléments ayant chacun une priorité
représentée par un nombre entier positif.
79
Conception et Analyse d’algorithmes
Activités d’apprentissage
Introduction
Le tri par tas est un très bon algorithme, mais une bonne implémentation du tri rapide est
généralement plus performante en pratique. Néanmoins, la structure de données tas offre
intrinsèquement de gros avantages. Dans cette activité, On va présenter l’une des applications
les plus répandues du tas, à savoir la gestion d’une file de priorité efficace. Comme c’est le cas
avec les tas, il existe deux sortes de files de priorité : les files max et les files min.
Définition
Une file de priorité est un type abstrait de données qui permet de gérer un ensemble S
d’éléments, dont chacun a une valeur associée baptisée clé.
INSÉRER(S, x) insère l’élément x dans l’ensemble S. Cette opération pourrait s’écrire sous la
forme
Une file de priorité min est munie des opérations INSÉRER, MINIMUM, EXTRAIREMIN et
DIMINUER-CLÉ.
Implémentation
MAXIMUM-TAS(A)
retourner A[1]
80
Unité 4. Structures de données spécialisées
La procédure EXTRAIRE-MAX-TAS :
EXTRAIRE-MAX-TAS(A)
si taille[A] < 1
max ← A[1]
A[1] ← A[taille[A]]
taille[A] ← taille[A] − 1
ENTASSER-MAX(A, 1)
retourner max
La procédure commence par modifier la clé de l’élément A[i] pour lui donner sa nouvelle valeur.
Accroître la clé de A[i] risque d’enfreindre la propriété de tas max ; la procédure, d’une manière
qui rappelle la boucle d’insertion, parcourt donc un chemin reliant ce nœud à la racine, afin de
trouver une place idoine pour la clé qui vient d’être augmentée. Tout au long du parcours, elle
compare un élément à son parent ; elle permute les clés puis continue si la clé de l’élément est
plus grande, et elle s’arrête si la clé de l’élément est plus petite, vu que la propriété de tas max
est alors satisfaite.
AUGMENTER-CLE-TAS(A, i, cle)
i <- PARENT(i)
INSÉRER-TAS-MAX(A, clé)
81
Conception et Analyse d’algorithmes
Conclusion
On peut conclure qu’un tas permet de faire toutes les opérations de file de priorité sur un
ensemble de taille n en un temps O(lg n).
Évaluation
Files de priorités et tas
Nous allons étudier ici une nouvelle structure de données : les files de priorité, et nous verrons
qu’un certain type d’arbres permet de les représenter de manière extrêmement efficace.
Définition. Intuitivement, une file de priorité est un ensemble d’éléments à qui sont attribués
un rang de priorité avant qu’ils ne rentrent dans la file, et qui en sortiront précisément selon
leur rang : l’élément de rang le plus élevé sera ≪ servi ≫ en premier. En d’autres termes, il
s’agit d’une structure de données sur laquelle opèrent les trois opérations suivantes :
• une fonction d’insertion d’un élément dans la file (avec son rang de priorité),
• une fonction qui renvoie l’élément de rang le plus élevé,
• une fonction qui supprime d’élément de rang le plus élevé de la file.
Parmi les différentes possibilités de codage des files de priorité, nous utiliserons la structure
dite de tas ou maximier (heap en Anglais). Les autres possibilités (file d’attente d’éléments
non triés, tableau trié) impliquent ou bien un calcul du maximum en temps linéaire, ou alors le
maintien d’un ordre entre tous les éléments qui n’est pas nécessaire. Une structure de tas est
un arbre satisfaisant les propriétés suivantes :
– c’est un arbre binaire complet, c’est-à-dire un arbre dont tous les niveaux de profondeurs
sont remplis, à l’exception du dernier, celui qui ne comporte que des feuilles, lesquelles sont
rangées ≪ le plus à gauche possible ≫
82
Unité 4. Structures de données spécialisées
Montrons maintenant comment employer un tas pour coder une file de priorité. Tout d’abord,
le codage de la fonction qui renvoie le maximum est très simple : il suffit de renvoyer la clef
contenue dans la racine (si le tas n’est pas vide, bien sûr). Cette opération peut donc s’exécuter
en temps constant.
En ce qui concerne la fonction d’insertion d’un élément, son principe est le suivant :
83
Conception et Analyse d’algorithmes
Correction
Présentation
Comme son nom l’indique un Arbre Binaire de Recherche (ABR) est organisé comme un arbre
binaire. Il est étiqueté par des éléments d’un ensemble
tous les nœuds du sous-arbre gauche de n sont étiquetés par des éléments b tels que b ≤ a
, ET
tous les nœuds du sous-arbre droit de n sont étiquetés par des éléments b tels que b ≤ a
84
Unité 4. Structures de données spécialisées
Évaluation
Exercice 1 :
1. Considérer l’ensemble des clés 1, 4, 5, 10, 16, 17, 21. 1. Dessiner des
arbres binaires de recherche de cet ensemble de clés avec une hauteur
de 2, puis 4, et ensuite 6.
Exercice 2 :
2. Ecrire une fonction function max(noeud : p_t _noeud ):integer qui calcule
le maximum de l’arbre de recherche.
85
Conception et Analyse d’algorithmes
Correction
Exercice 1 :
Exercice 2 :
integer;
gauche : p_t_noeud;
droite : p_t_noeud;
END;
86
Unité 4. Structures de données spécialisées
temp := noeud;
max := noeud^.cle ;
noeud := noeud^.droite;
end;
temp := noeud;
begin
min := noeud^.cle ;
noeud := noeud^.droite;
end;
result := min;
end;
87
Conception et Analyse d’algorithmes
Introduction
Certaines applications imposent de regrouper
éléments distincts dans une collection d’ensembles disjoints. Pour cela il est nécessaire de
savoir à quel ensemble appartient un élément donné et de pouvoir réunir deux ensembles.
Dans cette unité, on va étudier des méthodes permettant de gérer une structure de données
qui supporte ces opérations.
Une structure de données d’ensembles disjoints (UNION-FIND data structure) est une structure
de données qui maintient à jour une collection
d’ensemble dynamique disjoint. Chaque ensemble est identifié par un représentant, qui est un
certain membre de l’ensemble.
CREER _ENSEMBLE(x) : une procédure qui permet de créer un nouvel ensemble dont le
seul membre (et donc le représentant) est x. Comme les ensembles sont disjoints, il faut que x
ne soit pas déjà membre d’un autre ensemble.
Application
L’une des nombreuses applications des structures de données d’ensembles disjoints apparaît
lorsqu’il s’agit de déterminer les composantes connexes d’un graphe non orienté.
Connected-components(G)
Make-Set(D, v)
for each
if Find-Set(D, u)
Find-Set(D, v)
Union(D, u, v)
88
Unité 4. Structures de données spécialisées
Same-component(u, v)
if Find-Set(D, u) == Find-Set(D, v)
return true
Une manière simple d’implémenter une structure de données d’ensembles disjoints utilise des
listes chaînées:
Analyse du temps
Avec cette représentation en liste chaînée, CREER _ENSEMBLE(x) , et Find(D, x) sont facile à
implémenter, et consomment au pire des cas. L’implémentation la plus simple de l’opération
UNION(x; y), exécutée par concaténation de la liste de x à la fin de la liste de y, consomme
beaucoup plus de temps, même θ(n) au pire des cas.
n de la liste de y, consomme beaucoup plus de temps, même (n) au pire des cas.
Conclusion
89
Conception et Analyse d’algorithmes
Résumé de l’unité
Cette unité vous a permis d’étudier les structures de données spécialisées, de voir un exemple
d’application de l’ensemble disjoint pour calculer les composantes connexes d’un graphe et la
représentation des ensembles disjoints en utilisant les listes chaînées.
Évaluation de l’unité
Test
Directives
Les barèmes sont fixés devant chaque question
2. Ecrire une fonction function max(noeud : p_t _noeud ):integer qui calcule
le maximum de l’arbre de recherche.
Réponses
integer;
gauche : p_t_noeud;
droite : p_t_noeud;
END;
90
Unité 4. Structures de données spécialisées
temp := noeud;
max := noeud^.cle ;
noeud := noeud^.droite;
end;
temp := noeud;
begin
min := noeud^.cle ;
noeud := noeud^.droite;
end;
result := min;
end;
91
Conception et Analyse d’algorithmes
Résumé de l’unité
Ce module vous a permis d’avoir quelques-unes des techniques avancées de conception et
d’analyse d’algorithmes. Ainsi, tous les grands thèmes de l’algorithme ont été abordés dans
le cours : récursivité, Complexité temporelle et spatiale d’un algorithme, programmation
linéaire, NP-complétude, programmation dynamique, algorithmes probabilistes, algorithmes
d’approximation, etc.
92
Unité 4. Structures de données spécialisées
Évaluation du cours
Contrôle continu Test1
Directives
Test
Système de notation
1. (1.5 point) Donnez la différence entre les notations O() et Ω() sans donner
leur définition formelle.
93
Conception et Analyse d’algorithmes
Correction
Exercice 1 :
1. Faux
2. Faux
3. Vrai
Exercice 2 :
exprime une borne supérieure sur la consommation de ressources, alors que Ω()
Exercice 3 :
1.
2.
94
Unité 4. Structures de données spécialisées
Test
Système de notation
Exercice 1 (4 points)
Exercice 2 (4 points)
2. (5 points) Quelle est la somme des poids des arêtes de l’arbre minimal
couvrant T ?
95
Conception et Analyse d’algorithmes
Correction
Exercice 1
j, k : entier;
T.element[i] := T.element[T.taille]; \\
T.taille-- ;
j:=i; \\
k:=2*j+1
return(T);
fin delete
Exercice 2
96
Unité 4. Structures de données spécialisées
Références du cours
97
Siège de l’Université Virtuelle Africaine
PO Box 25405-00603
Nairobi, Kenya
contact@avu.org
oer@avu.org
bureauregional@avu.org
2017 UVA