Académique Documents
Professionnel Documents
Culture Documents
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique1
Table of Contents
Cours Algorithmique : Objectifs et compléments........................................................................................1
Notations mathématiques.......................................................................................................................4
Analyse de la complexité.........................................................................................................................4
Algorithmique ensembliste.....................................................................................................................4
La concurrence........................................................................................................................................5
Item 3:.................................................................................................................................................5
Les tris.....................................................................................................................................................7
Problèmes divers.....................................................................................................................................8
Summary of Operators................................................................................................................................9
Arithmetic Operators...........................................................................................................................9
Unary Operators..................................................................................................................................9
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique2
Equality and Relational Operators.......................................................................................................9
Conditional Operators.........................................................................................................................9
Les collections...........................................................................................................................................10
Lister les opérations de base réalisables sur une collection, en précisant le résultat attendu..............10
Donner pour chacune des collections suivantes ses spécifications contractuelles :.............................10
Pour chacune des implémentations de collections données dans le tableau ci-dessous, donner la
complexité de chaque opération de base..............................................................................................10
Note : références...............................................................................................................................11
Définitions.............................................................................................................................................14
Tri......................................................................................................................................................14
Tri stable............................................................................................................................................14
Sélec tion...........................................................................................................................................15
Insertion............................................................................................................................................15
Rapide................................................................................................................................................15
Fusion................................................................................................................................................15
Pour la suite.......................................................................................................................................15
Algorithmique ensembliste.......................................................................................................................20
Ecrire des algorithmes ensemblistes efficaces dans un contexte multi-niveaux et pouvoir analyser la
complexité de chaque niveau................................................................................................................24
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique4
Objectifs du cours d’Algorithmique
Etapes de conception d’algorithmes
1) Lister ces étapes en donnant leur rôle
a. Prendre connaissance du problème ou le poser
b. Enoncer le principe de la solution
c. Pré estimation de l’ordre de grandeur de la complexité
d. Valider le principe
e. Ecrire l’algorithme en le commentant
f. Le tester (preuve théorique du fonctionnement + exécutant avec succès des cas de
tests)
g. [Analyse précise de complexité]
2) Reconnaître si l’une des ces étapes manque dans la présentation d’un algorithme
3) Pouvoir lister les principales stratégies (12) de conception d’algorithmes (diviser pour régner,
programmation dynamique, systèmes experts, algorithmes gloutons, algorithmes probabilistes,
simulations, algorithmes génétiques….), et donner pour chaque stratégie son principe. Il ne
s’agit pas ici d’acquérir l’expertise de toutes ces techniques, mais simplement de savoir qu’elles
existent et l’idée qui les sous-tend, afin de pouvoir approfondir la recherche devant un
problème concret.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique5
h. Opérateurs de contrôle de flux (9)
Notations mathématiques
Définir les notations O, thêta et Omega.
Analyse de la complexité
1) Définir la complexité en temps et la complexité en espace
2) Lister et définir les divers niveaux de complexité en temps
3) Donner les principaux ordres de complexité, en disant quels principes de conception mènent à
ces ordres
4) Définir le pire des cas, le cas moyen et le meilleur des cas
5) Etre capable de calculer la complexité dans les algorithmes itératifs avec évaluation simple du
nombre d’entrées dans les boucles.
6) Etre capable de calculer la complexité dans les algorithmes récursifs avec évaluation simple du
nombre d’entrées dans les boucles (ref : introduction to algorithms, cours sur la recursivité et
MIT courses).
a. Décrire l’approche diviser pour la conception des algorithmes
b. Ecrire la suite décrivant la complexité pour un algorithme récursif
c. Enoncer et appliquer le théorème général de récurrence
d. Résoudre les récursivités triviales
e. Dérécursiver les algorithmes.
7) Donner la formule de calcul de la complexité dans le cas où le nombre d’opérations est une
variable aléatoire.
8) Etre capable d’évaluer la complexité des algorithmes dans les cas pas très complexes
9) Pouvoir décrire les situations dans lesquelles renoncer à l’optimalité pour l’efficacité
10) Donner un ou deux cas de choix d’efficacité au détriment de l’optimalité, avec les gains obtenus.
11) Savoir réaliser la multiplication d’entiers et l’élévation à la puissance en O(ln(n)), le calcul des
polynômes en O(n)
Algorithmique ensembliste
12) Enoncer le principe de base de l’algorithmique ensembliste
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique6
13) Donner les inconvénients des algorithmes unitaires purs
14) Donner les inconvénients des algorithmes globaux purs
15) Enoncer l’algorithme de base général de traitement ensembliste
16) Ecrire des algorithmes ensemblistes efficaces dans un contexte multi-niveaux et pouvoir
analyser la complexité de chaque niveau.
La concurrence
Item 3:
http://cimi01/javatutorial/extra/certification/index.html
1) Définir les processus et les threads, et dire quelle est leur différence
2) Dire quels sont les deux principaux problèmes posés par les accès concurrents, tout en étant
capable d’identifier ou de décrire des situations susceptibles de poser ces problèmes.
3) Définir ce qu’est un ensemble d’opérations synchronisées
4) Réaliser la synchronisation des opérations grâce aux moniteurs (Lock)
5) Lister et décrire les trois principaux problèmes fonctionnels posés par la synchronisation.
6) Etre capable d’identifier les situations susceptibles de poser les problèmes de synchronisation
7) Décrire et être capable d’identifier les problèmes de performance posés par la synchronisation
8) Etre capable de réaliser la synchronisation par les accès atomiques et les variables atomiques.
9) Savoir utiliser les mécanismes de synchronisation wait, sleep, notify, join
10) Etre capable d’écrire des codes corrects du point de vue fonctionnel et du point de vue de la
performance dans un contexte d’accès concurrent.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique7
8) Être capable de donner pour chacune des implémentations de ces collections les algorithmes
des opérations de base en présence de concurrence.
9)
10) Être capable de donner pour chacune des implémentations de ces collections les algorithmes
des opérations de base en présence de concurrence.
11) Définir les structures de cache, de pool et d’archive
12) Énoncer les problèmes d’insertion et de suppression d’un élément du Cache
13) Lister cinq stratégies de base de gestion du cache, en expliquant chacune d’entre elles :
LIFO, FIFO, Random, LRU, LFU, custom. Donner pour chaque stratégie (en dehors de
custom) une implémentation appropriée de la structure de cache.
14) Lister les principaux mécanismes de synchronisation du cache, en précisant pour chaque
mécanisme ses avantages et ses inconvénients
15) Fournir les algorithmes implémentant les divers mécanismes de synchronisation du cache
16) Lister les stratégies de gestion de pool en expliquant leur fonctionnement
17) Reconnaître les situations dans lesquelles il est souhaitable d’utiliser un pool, un cache ou
une archive.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique8
2) Lister les deux fonctions de tests les plus utilisées, ainsi que les deux mesures les plus utilisées
pour les tests.
3) Donner le principe des mesures de test ensemblistes
4) Définir la notion de classe d’équivalence de test
5) Identifier les classes d’équivalence de base pour les divers types de données
6) Penser au test et décrire les scénarios de test avant de penser à l’algorithme
7) Savoir utiliser des outils pour produire des scénarios de tests pairwise, uniwise
8) Savoir se servir d’un logger
a. Créer le logger
b. Spécifier le niveau de log
c. logger
9) Savoir ce servir d’un debugger
a. Lancement
b. Définition des points d’arrêt
c. Exécution pas à pas
d. Exécution détaillée
e. Observation de la valeur des variables
f. Mise en place des points d’arrêt dans les boucles
Les tris
Donner le principe, l'ordre de complexité, les limites d’utilisation et les algorithmes de tris suivants :
Le tri rapide
Le tri fusion
Le tri dénombrement
Savoir combiner les tris pour obtenir des tris plus efficaces
Note : Pour le premier semestre, on s’arrête à l’ordre de complexité et aux limites d’utilisation.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique9
Algorithmes pour bases de données
Voir SQL 02, requêtes avancées.
Problèmes divers
Avoir une idée des grands thèmes tels que la machine de Turing,
la calculabilité d'Alonso-Church et l'incomplétude de Gödel.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique10
Quelques éléments de cours
Note : ceci est un complément des notes issues de la littérature et remises aux étudiants. En grande
partie ici, il s’agit d’une production personnelle pour compléter.
….), et donner pour chaque stratégie son principe. Il ne s’agit pas ici d’acquérir l’expertise de
toutes ces techniques, mais simplement de savoir qu’elles existent et l’idée qui les sous-tend,
afin de pouvoir approfondir la recherche devant un problème concret.
Notations mathématiques
Définir les notations O, thêta et Omega.
Analyse de la complexité
17) Définir la complexité en temps et la complexité en espace
18) Lister et définir les divers niveaux de complexité en temps
19) Donner les principaux ordres de complexité, en disant quels principes de conception mènent à
ces ordres
20) Définir le pire des cas, le cas moyen et le meilleur des cas
21) Etre capable de calculer la complexité dans les algorithmes itératifs avec évaluation simple du
nombre d’entrées dans les boucles.
22) Etre capable de calculer la complexité dans les algorithmes récursifs avec évaluation simple du
nombre d’entrées dans les boucles (ref : introduction to algorithms, cours sur la recursivité et
MIT courses).
a. Décrire l’approche diviser pour la conception des algorithmes
b. Ecrire la suite décrivant la complexité pour un algorithme récursif
c. Enoncer et appliquer le théorème général de récurrence
d. Résoudre les récursivités triviales
e. Dérécursiver les algorithmes.
23) Donner la formule de calcul de la complexité dans le cas où le nombre d’opérations est une
variable aléatoire.
24) Etre capable d’évaluer la complexité des algorithmes dans les cas pas très complexes
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique12
25) Pouvoir décrire les situations dans lesquelles renoncer à l’optimalité pour l’efficacité
26) Donner un ou deux cas de choix d’efficacité au détriment de l’optimalité, avec les gains obtenus.
27) Savoir réaliser la multiplication d’entiers et l’élévation à la puissance en O(ln(n)), le calcul des
polynômes en O(n)
Algorithmique ensembliste
28) Enoncer le principe de base de l’algorithmique ensembliste
29) Donner les inconvénients des algorithmes unitaires purs
30) Donner les inconvénients des algorithmes globaux purs
31) Enoncer l’algorithme de base général de traitement ensembliste
32) Ecrire des algorithmes ensemblistes efficaces dans un contexte multi-niveaux et pouvoir
analyser la complexité de chaque niveau.
La concurrence
Item 3:
http://cimi01/javatutorial/extra/certification/index.html
11) Définir les processus et les threads, et dire quelle est leur différence
12) Dire quels sont les deux principaux problèmes posés par les accès concurrents, tout en étant
capable d’identifier ou de décrire des situations susceptibles de poser ces problèmes.
13) Définir ce qu’est un ensemble d’opérations synchronisées
14) Réaliser la synchronisation des opérations grâce aux moniteurs (Lock)
15) Lister et décrire les trois principaux problèmes fonctionnels posés par la synchronisation.
16) Etre capable d’identifier les situations susceptibles de poser les problèmes de synchronisation
17) Décrire et être capable d’identifier les problèmes de performance posés par la synchronisation
18) Etre capable de réaliser la synchronisation par les accès atomiques et les variables atomiques.
19) Savoir utiliser les mécanismes de synchronisation wait, sleep, notify, join
20) Etre capable d’écrire des codes corrects du point de vue fonctionnel et du point de vue de la
performance dans un contexte d’accès concurrent.
21) Utiliser l’architecture fork/join de java pour écrire des programmes parrallèles pour les
processeurs multicoeurs
22) Décrire les patterns et les anti-patterns de parrallelisation des programmes pour le multicoeur
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique13
21) Pour chacune des implémentations de collections données dans le tableau ci-dessous,
donner la complexité de chaque opération de base. Faire de même pour les listes ordonnées.
22) Citer les collections les plus appropriées du point de vue complexité pour répondre à la
requête consistant à fournir les éléments contenus dans une plage, ainsi que pour chaque
opération de base.
23) Lister en donnant leur rôle les collections EnumSet, EnumMap, WeakHashMap,
ConcurrentHashMap, SKIPLIST
24) Être capable de donner pour chacune des implémentations de ces collections (du 4,5,6) les
algorithmes des opérations de base dans un contexte non concurrent.
a. Pour les arbres, il faudra également pouvoir donner les divers algorithmes de
parcours des arbres : parcours préfixé, parcours infixé, parcours postfixé traversée
hiérarchique.
b. Pour les tables de hachage, il faut donner les diverses techniques et fonctions de
hachage, jusqu’au hachage universel.
25) Être capable de donner pour chacune des implémentations de ces collections les algorithmes
des opérations de base en présence de concurrence.
26)
27) Être capable de donner pour chacune des implémentations de ces collections les algorithmes
des opérations de base en présence de concurrence.
28) Définir les structures de cache, de pool et d’archive
29) Énoncer les problèmes d’insertion et de suppression d’un élément du Cache
30) Lister cinq stratégies de base de gestion du cache, en expliquant chacune d’entre elles :
LIFO, FIFO, Random, LRU, LFU, custom. Donner pour chaque stratégie (en dehors de
custom) une implémentation appropriée de la structure de cache.
31) Lister les principaux mécanismes de synchronisation du cache, en précisant pour chaque
mécanisme ses avantages et ses inconvénients
32) Fournir les algorithmes implémentant les divers mécanismes de synchronisation du cache
33) Lister les stratégies de gestion de pool en expliquant leur fonctionnement
34) Reconnaître les situations dans lesquelles il est souhaitable d’utiliser un pool, un cache ou
une archive.
Les tris
Donner le principe, l'ordre de complexité, les limites d’utilisation et les algorithmes de tris suivants :
Le tri rapide
Le tri fusion
Le tri dénombrement
Savoir combiner les tris pour obtenir des tris plus efficaces
Note : Pour le premier semestre, on s’arrête à l’ordre de complexité et aux limites d’utilisation.
Problèmes divers
Avoir une idée des grands thèmes tels que la machine de Turing,
la calculabilité d'Alonso-Church et l'incomplétude de Gödel.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique16
Summary of Operators
The following quick reference summarizes the operators supported by the Java programming language.
Arithmetic Operators
+ Additive operator (also used for String concatenation)
- Subtraction operator
* Multiplication operator
/ Division operator
% Remainder operator
Unary Operators
+ Unary plus operator; indicates positive value (numbers are positive
without this, however)
- Unary minus operator; negates an expression
++ Increment operator; increments a value by 1
-- Decrement operator; decrements a value by 1
! Logical compliment operator; inverts the value of a boolean
Conditional Operators
&& Conditional-AND
|| Conditional-OR
?: Ternary (shorthand for if-then-else statement)
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique17
Les collections
Définir une collection
Collection : objet regroupant plusieurs éléments en une seule entité. Il y a toujours un moyen de
parcourir tous les éléments d’une collection ; on appellera ce moyen un littérateur.
NB : pour les complexités données pour les listes, les opérations d’insertion et de suppression sont
censées ne pas inclure de recherche.
Note : références
Il est important de noter que pour toutes les données autres que les types primitifs (objets,
enregistrements, collections,…) les collections ne stockent que les références à ces données, et non
leurs valeurs. Ainsi, en mettant deux fois la même donnée dans une collection, seule la référence est
dupliquée, la donnée ne l’est pas. Cela permet de construire des collections complexes utilisant diverses
implémentations pour réaliser diverses opérations.
Algorithme A-étoile
Début
Fin TQ
Fin
Archive : ensemble d’objets dont l’usage est très rare, et qui par conséquent ont été stockés
d’une manière compréssée pour gagner de l’espace, et surtout dans un espace dédié hors
de la collection stockant les autres objets semblables, pour gagner du temps lors du
traitement de ces autres objets.
36) Lister cinq stratégies de base de gestion du cache, en expliquant chacune d’entre elles :
LIFO : le dernier élément entré est le premier sorti
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique20
LRU : on fait sortir l’élément le moins recemment utilisé
Donner pour chaque stratégie (en dehors de custom) une implémentation appropriée de la
structure de cache.
LIFO : pile
Random :
LRU : LinkedHashMap
LFU :
37) Lister les principaux mécanismes de synchronisation du cache, en précisant pour chaque
mécanisme ses avantages et ses inconvénients
a. Attente active. On revient régulièrement voir si l’original des données mises en cache
à changé. Si c’est le cas, on remplace les données du cache par les nouvelles.
b. Délai de validité. Les données mises dans le cache sont considérées comme
invalides avant un certain délai. Dès que ce délai est passé, elles sont déclarées
invalides et remplacées par de nouvelles données.
c. Auditeurs. Le cache enregistre un auditeur auprès de la source des données mises
en cache. Dès qu’une donnée est modifiée, l’auditeur en est informé et met à jour le
cache selon cette modification.
38) Fournir les algorithmes implémentant les divers mécanismes de synchronisation du cache
39) Lister les stratégies de gestion de pool en expliquant leur fonctionnement
Le problème principal est ici de savoir comment faire lorsque toutes les ressources du pool
sont occupées. On peut :
a) Bloquer le programme qui demande une nouvelle ressource jusqu’à ce qu’elle soit
disponible
b) Renvoyer une ressource nulle ou une exception
c) Créer une nouvelle ressource qui sera détruite dès sa restitution au Pool.
d) Utiliser une autre stratégie de gestion.
40) Reconnaître les situations dans lesquelles il est souhaitable d’utiliser un pool, un cache ou
une archive.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique21
Résumé sur les tris
Définitions
Tri
Un tri classe les données d’un tableau dans un ordre défini. Par défaut, il s’agit de l’ordre croissant.
Tri stable
Un tri est dit stable, si lors de l’opération de tri, l’ordre de deux éléments d’égale valeur reste inchangé.
Tris généraux
Tris linéaires
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique22
Base N N N 1
Insertion
On fait n itérations.
sont triés.
Rapide
On partage la liste à trier en deux sous-listes telles que tous les éléments de la première soient plus
petits que les éléments de la seconde. Par récurrence, on trie les deux sous-listes.
La liste d’origine est donc coupée en trois : une première liste (à gauche) composée des éléments _ au
pivot, le pivot (à sa place définitive) et une liste (à droite ) composée des éléments > au pivot.
Fusion
On appelle ce tri mergesort en anglais.
Le principe est de diviser une table de longueur n en deux tables de longueur n/2, de trier récursivement
ces deux tables, puis de fusionner les tables triées.
Pour la suite
Voir algo T1-tris, et voir introduction à l’algorithmique
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique23
EnumSet, EnumMap=set et map à utiliser pour les clés prises dans un ensemble énuméré (l’ensemble
est défini par l’énumération de la liste de ses éléments).
WeakHashMap=HashMap dont les entrées sont supprimées de la mémoire si elles n’ont pas d’autre
référence que cette HashMap
ConcurrentHashMap=HashMap optimisée pour les accès concurrents.
SKIPLIST=
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique24
Définir les structures de cache, de pool et d’archive (ref:
javaperformance)
Pool: ensemble d’objets dont la création est couteuse, qui ont été stockés pour des
utilisations futures. Pour prendre un objet, on le récupère du pool, et quand on a fini de s’en
servir on le remet au pool.
Archive : ensemble d’objets dont l’usage est très rare, et qui par conséquent ont été stockés
d’une manière compréssée pour gagner de l’espace, et surtout dans un espace dédié hors
de la collection stockant les autres objets semblables, pour gagner du temps lors du
traitement de ces autres objets.
43) Lister cinq stratégies de base de gestion du cache, en expliquant chacune d’entre elles :
LIFO : le dernier élément entré est le premier sorti
Donner pour chaque stratégie (en dehors de custom) une implémentation appropriée de la
structure de cache.
LIFO : pile
Random : ?
LFU : ?
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique25
44) Lister les principaux mécanismes de synchronisation du cache, en précisant pour chaque
mécanisme ses avantages et ses inconvénients
a. Attente active. On revient régulièrement voir si l’original des données mises en
cache à changé. Si c’est le cas, on remplace les données du cache par les nouvelles.
b. Délai de validité. Les données mises dans le cache sont considérées comme
invalides avant un certain délai. Dès que ce délai est passé, elles sont déclarées
invalides et remplacées par de nouvelles données.
c. Auditeurs. Le cache enregistre un auditeur auprès de la source des données mises
en cache. Dès qu’une donnée est modifiée, l’auditeur en est informé et met à jour le
cache selon cette modification.
45) Fournir les algorithmes implémentant les divers mécanismes de synchronisation du cache
???
46) Lister les stratégies de gestion de pool en expliquant leur fonctionnement
Le problème principal est ici de savoir comment faire lorsque toutes les ressources du pool
sont occupées. On peut noter ici quatre stratégies résumées dans le sigle BECA:
e) Blocage: Bloquer le programme qui demande une nouvelle ressource jusqu’à ce qu’elle
soit disponible
f) Exception : Renvoyer une ressource nulle ou une exception
g) Création : Créer une nouvelle ressource qui sera détruite dès sa restitution au Pool.
h) Autre : Utiliser une autre stratégie de gestion.
47) Reconnaître les situations dans lesquelles il est souhaitable d’utiliser un pool, un cache ou
une archive.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique26
Séries aléatoires (52)
Le programmeur a parfois besoin de créer des séries aléatoires dans ses programmes. Par exemple, pour
proposer un programme générant des épreuves de manière aléatoire pour des candidats à partir des
questions prises dans une base de données. Il serait souhaitable que pour des jours différents, le
candidat n’ait pas toujours la même épreuve.
Pour générer une série aléatoire, les langages de programmation offrent les générateurs de nombre
pseudo aléatoires. Ce sont des nombres dont il est mathématiquement prouvé que la répartition
correspond à une série aléatoire. Malheureusement, la plupart des générateurs de nombre pseudo-
aléatoires fournissent une série qui est toujours la même chaque fois que le générateur est relancé
(premier lancement du générateur par le compilateur). En java, vous pouvez avoir un nombre aléatoire
en appelant la fonction Math.random(). Nous exposons juste ici une astuce pour s’assurer qu’on a une
véritable génération de nombres aléatoires avec le générateur de la classe Math. On peut utiliser le code
suivant :
void initRandom(){
for (int i=0 ;i<l ;i++) Math.random() ;// initialise le générateur de nombre aléatoires à
//une valeur quelconque
le générateur étant initialisé à une valeur quelconque (aléatoire), la série issue de ce générateur sera
une série aléatoire. Je veux dire que tout nombre obtenu après la boucle ci-dessus en faisant
Math.random() peut être réellement considéré comme un nombre aléatoire.
Il faut tout de même noter que le caractère aléatoire de la série ci-dessus vient simplement du fait
qu’ on ne connaît pas le nombre auquel elle démarre. Mais il est possible que ce générateur produise
deux séries identiques (si les valeurs de l obtenues après le modulo sont les mêmes). Il est également
possible qu’il produise deux sous -séries identiques. Il suffit pour cela que pour une série A l prenne une
valeur l0 et que pour une autre série B, l prenne une valeur l 1<l0. la série A sera entièrement contenue
dans B, ce qui n’est pas toujours souhaitable. Si on souhaite remédier à ce problème, on peut utiliser la
fonction random suivante, pour un générateur initialisé selon la procédure initRamdom ci-dessus.
float random(){
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique27
long l=System.currentTimeMillis() ;// donne l’instant présent en //millisecondes
l=l%3 ; // fournit un nombre entre 0 et 3. On pourrait choisir tout autre //petit nombre
return Math.random() ;
cette nouvelle fonction random renvoie réellement une série aléatoire si on suppose que
System.currentTimeMillis() renvoie des valeurs différentes entre les divers appels. Cela n’est vrai que si
la durée totale d’exécution du programme est supérieure à 1ms. Ce qui pourrait ne pas être le cas pour
certains programmes de simulations sur des machines très rapides. Il faut ici noter que l’appel à
System.currentTimeMillis() pour faire une différence n’est pas toujours correct à cause de la restriction
ci-dessus mentionnée. C’est la raison pour laquelle System.currentTimeMillis() n’a pas été utilisé pour
différentier les objets des TreeSet ci-dessus.
Nous allons maintenant proposer une approche permettant d’être à peu près sûrs qu’au sein de la
même machine virtuelle et quelle que soit la durée d’exécution du programme, il n’est pas possible
d’obtenir deux séries identiques.
class Randomizer{
long l1=0 ;
void initRandom(){
for (int i=0 ;i<l ;i++) Math.random() ;// initialise le générateur de nombre
aléatoires à //une valeur quelconque
float random(){
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique28
long l=System.currentTimeMillis() ;// donne l’instant présent en
//millisecondes
synchronized(synchro){
count++ ;
if(l==l1) l+=count ;
l1=l;
return Math.random() ;
Que se passerait-il au sein de machines différentes ? Il reste possible d’obtenir des séries identiques,
mais la probabilité que cela arrive est très faible. Pour réduire cette probabilité, on ferait que le
compteur count soit fournit par un objet accessible en réseau par toutes les machines. On pourrait
également appliquer à count un coefficient multiplicateur dépendant uniquement de la machine, ce qui
garantirait que pour des machines pour lesquelles ce coefficient est différent, les séries ne sauraient être
identiques.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique29
Algorithmique ensembliste
Enoncer les principes de base de l’algorithmique ensembliste
1) Principe de la similitude : Un algorithme capable de réaliser de façon globale un traitement ou
des traitements similaires sur un ensemble d’éléments sera au moins aussi rapide que
l’algorithme qui réalise indépendamment ce traitement sur chacun des éléments, tant que
l’ensemble a une taille inférieure à un certain seuil
2) Principe du plus bas niveau : Lorsqu’on doit effectuer individuellement des traitement sur un
ensemble d’éléments se trouvant à un niveau de complexité donnée, il vaut mieux découper
l’ensemble en plusieurs blocs dont la taille est la taille maximale pouvant être efficacement
traitée au niveau de complexité plus bas, puis charger les éléments par bloc, les traiter au niveau
de complexité le plus bas, puis stocker les résultats.
Perdent beaucoup de temps dans les transferts de données et dans les lectures écritures.
« Réaliser un traitement T sur un ensemble de N éléments situés sur un disque dur, et stocker le
résultat du traitement sur le disque. »
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique30
a. Essayer de charger du disque de manière ensembliste (c'est-à-dire avec le minimum
d’accès disques ou de requêtes possibles (1 est idéal)) un bloc de taille b d’éléments
non traités.
b. Traiter ces éléments en mémoire par un algorithme approprié
c. Enregistrer les résultats sur le disque
Démarche itérative
Les éléments à traiter sont classés de telle sorte que pour passer du résultat r(n) du traitement de
l’élément n à celui de l’élément n+1, on réalise sur le couple (n,r(n)) des opérations dont la complexité
est faible par rapport au calcul à partir de rien (idéalement le passage se fait en O(1)).
Par exemple, dans le calcul d’une fonction selon une serie de Taylor, on doit calculer une somme de
xn/n !.
Dans un traitement unitaire, on va écrire une fonction puissance qui s’exécute au mieux en O(ln(n)) et
une fonction factorielle qui s’exécute en O(n) (avec en prime les problèmes de débordement et de
précision). Chaque terme de la serie sera donc calculé en O(n). La démarche itérative ici consiste à
déclarer une variable ti, initialisée à 0.0 . Pour passer au terme t i+1, on fera simplement t i=ti*x/(i+1). De
cette manière, on calcule chaque terme xn/n ! en O(1).
Démarche de cache
On stocke dans des variables ou dans une collection appelée cache (tableau, liste, dictionnaire,…)
certains résultats intermédiaires ou finaux des calculs effectués sur les éléments précedents. Ces
résultats sont utilisés pour accélerer le calcul courant.
Exemple, on souhaite par un développement de TayLor en dimension 2 calculer la valeur d’une fonction
f en un ensemble de points. On suppose que pour ces points on calculera à peu près le même nombre
de termes dans la serie. Dans le calcul des termes, on sera appelé à calculer C(k,j)/j ! . Ce calcul devrait
se faire pour chaque x dont on veut calculer la fonction. Pour éviter cela, on va faire un tableau stockant
les valeurs de C(k,j)/j !. pour cela, il faut trouver une fonction injective de complexité O(1) qui pour le
couple (k,j) fait correspondre un indice dans le tableau. Lors des calculs pour déterminer la valeur de
f(x0), on stockera les résultats de C(k,j)/j !. Pour tous les autres éléments, on se contentera d’utiliser ces
résultats, ce qui permet de les obtenir dans la suite en O(1).
Les principaux problèmes à résoudre dans la démarche de cache sont les suivants :
a) Identifier les résultats à stocker. Ce sont en général ceux qui seront utiles dans les calculs futurs
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique31
b) Définir la fonction d’indice. Il s’agit de la fonction permettant de déterminer pour une entrée
donnée la position du résultat correspondant dans la collection représentant le cache. Cette
définition n’est pas toujours aisée, mais elle est en général réalisable.
c) Choisir le type de collection à utiliser pour représenter le cache
d) Déterminer si la taille de cache devient très grande quelles données il faut en sortir
e) Si les résultats stockés dans le cache dépendent du temps, il devient nécessaire de s’assurer
également que ces résultats restent valides, s’ils viennent à être utilisés longtemps après leur
mise en cache.
Pour la plupart des problèmes, il suffit de répondre aux questions a, b et c. Pour certains problèmes, les
réponses à d et e sont nécessaires. Toute une section y est consacrée dans le chapitre sur la gestion des
caches.
Démarche de groupement
Ici, l’ensemble est supposé être constitué d’éléments quelconques. Chaque élément traité
individuellement a un certain coût. Si les éléments sont regroupés en blocs homogènes (le critère
d’homogeneïté étant à définir par vous même), on peut appliquer une démarche itérative pour le
traitement des blocs ou une démarche de cache sur chaque bloc.
Exemple: calcul de valeurs de fonctions définies par morceaux sur des rectangles pour une liste
d’éléments en 2D
Démarche destructive
Les traitements sont faits sur les éléments d’un ensemble, en conservant chaque fois une propriété
vérifiée par cet ensemble. Le fait de maintenir la propriété conservée à chaque traitement accroît la
complexité de réalisation de ce traitement. On évalue alors la possibilité de traiter tous les éléments à
traiter, sans conserver pendant le traitement les propriétés de l’ensemble. Une fois que tous les
éléments sont traités, on restructure l’ensemble pour qu’il vérifie la propriété qui était violée.
La démarche hiérarchique
Ici, on calcule par étapes plusieurs résultats intermédiaires qui seront utilisés pour obtenir le résultat
final de chaque élément. La connaissance de tous les éléments au départ permet de réaliser
efficacement cette opération.
La démarche constructive
Pour exécuter un traitement concernant plusieurs éléments d’un ensemble, on commence par
construire un ensemble (qui peut être le même) ayant des propriétés facilitant le traitement à réaliser.
Une fois cet ensemble construit, les traitements peuvent être plus facilement réalisés.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique32
Exple : recherche de plusieurs éléments sur un ensemble non trié. On peut commencer par réaliser le tri
de cet ensemble, ce qui permettra par la suite de faire une recherche dichotomique qui est en O(lnn),
plutôt qu’une recherche linéaire en O(n).
La démarche créative
La création d’un ensemble (tableau) pour factoriser un code d’elts separés
La démarche référentielle
S’appuyer sur un élément de référence. Construire une norme par exemple.
On peut également, plutôt que de faire un traitement sur un ensemble d’éléments, se contenter de le
faire sur un élément de référence, et de renvoyer le résultat sur un élément précis seulement à la
consultation dudit élément.
Par exemple, plutôt que d’échanger les éléments de deux lignes d’une matrice, on peut entretenir un
vecteur de pivot nous indiquant les lignes qui auraient dues être échangées. Ainsi, plutôt que d’échanger
les lignes de la matrice, on échange les éléments du pivot. Le pivot est tel que p[i]=j, signifie que la ième
ligne actuelle de la matrice est plutôt celle qui était la jième ligne au départ.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique33
Les types de données en java
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique34
LES TYPES DE BASE
La taille des types de base est d�fini dans le langage et elle est donc ind�pendante de la machine ou
du syst�me d'exploitation. Le langage ne supporte pas les pointeurs.
Tout les types num�riques sont des types sign�s. Il n'existe pas de type num�rique non
sign�.
Des valeurs sp�ciales sont d�finies pour repr�senter les valeurs extr�mes des nombres
entiers :
java.lang.Byte.MIN_VALUE et java.lang.Byte.MAX_VALUE
java.lang.Short.MIN_VALUE et java.lang.Short.MAX_VALUE
java.lang.Int.MIN_VALUE et java.lang.Int.MAX_VALUE
java.lang.Long.MIN_VALUE et java.lang.Long.MAX_VALUE
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique35
Les types r�els :
Pour repr�senter les types r�els, Java utilise un sous ensemble la norme IEEE-754. Les deux types de
r�els impl�ment�s en Java sont :
3.40282347E+28 � 1.40239846E-45
32
float Signe=1 bit, mantisse=23 bits, exposant
bits
=8bits
1.79769313486231570E+308 �
64
4.9406545841246544E-324
double
bits
Signe=1 bit, mantisse=52 bits, exposant=11
bits
Des valeurs sp�ciales sont d�finies pour repr�senter les valeurs extr�mes des nombres
r�els :
java.lang.Float.POSITIVE_INFINITY et
java.lang.Float.NEGATIVE_INFINITY
java.lang.Float.NaN : (Not An Number) n'est pas un nombre. Certains calculs ne
donnent pas un r�sultat num�rique significatif, c'est alors cette valeur sp�ciale qui est
retourn�e.
Exemple : POSITIVE_INFINITY / NEGATIVE_INFINITY
java.lang.Float.MIN_VALUE et java.lang.Float.MAX_VALUE
java.lang.Double.POSITIVE_INFINITY et
java.lang.Double.NEGATIVE_INFINITY
java.lang.Double.NaN
java.lang.Double.MIN_VALUE et
java.lang.Double.MAX_VALUE
Le type caract�re :
Type Taille Intervalle
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique36
char 16 bits 0 � 65535
Le jeu de caract�res Java est le jeu Unicode (16 bits non sign�) permettant ainsi de coder les
alphabets du monde entier. Les 128 premiers caract�res sont les m�mes que ceux du code
ASCII.
Le type bool�en :
Laa comparaison entre 2 valeurs donne un r�sultat de type bool�en.
Le type boolean ne peut recevoir que 2 valeurs : true ou false et n'est pas compatible
avec un type num�rique.
Les conversions
Exemples :
double d = 12345.6;
byte b = (byte)d; // b vaut 57
Les conversions d’un type entier vers un autre type entier se font par troncature : on perd
les bits les plus à gauche.
Les conversions d’un flottant vers un entier commencent par une conversion de la valeur
du flottant en int ou long, puis il y a une conversion du type précédent.
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique37
Cours algorithmique, tous droits reserves. Copie pour utilisation exclusive des étudiants de
Polytechnique38
i Avec une grande probabilité
Algorithmique : Science disant comment devant un problème, on peut définir une succession d’étapes qui
aboutissent à la résolution de ce problème (qui n’est pas forcement informatique)
Grandes orientations à garder à l’esprit quand on veut concevoir des algorithmes (15 principes):
1. Principe de l’inversion (très général : principe de conduite de la pensée pouvant s’appliquer partout)
3. Techniques heuristiques
4. Approches itératives
5. Approches ensemblistes
6. Programmation dynamique
7. Algorithmes gloutons
8. Systèmes experts
9. Algorithmes probabilistes
10. Simulations
I-Principe de l’inversion
Pour atteindre un objectif, on peut envisager une chose et on peut envisager aussi son contraire. L’idée du principe de
l’inversion c’est de dire le contraire ou la négation de l’idée que nous avons pour obtenir un résultat peut aussi être un
moyen pour obtenir ce résultat.
Un principe qui est le corolaire de celui de l’inversion (le principe de la dualité) stipule que la même cause peut produire
deux effets contraires ou alors que le même effet peut être dû à deux causes exactement opposées.
Exemple : Quelqu’un peut vous donner à manger parce qu’il vous aime ou alors parce qu’il vous déteste
C’est une sorte de couverture qui peut s’appliquer à tous les autres principes.
L’idée principale est de tester notre mot à partir de la première lettre : si c’est bon, on a trouvé la sous chaine,
sinon, on avance d’un caractère jusqu’à la fin du mot. Comment donc appliquer l’inversion sur cet exemple ? On
peut par exemple :
A la suite de Descartes, l’une des idées phare en algorithmique s’est que pour résoudre un problème, on le divise en sous-
problèmes plus faciles à résoudre, on résout ces sous-problèmes, et à la fin on aura résolu tout notre problème. On peut
aussi diviser l’espace dans lequel on résout le problème (en sous espaces) ou alors les données (en blocs) pour résoudre
notre problème. Quand on a un problème à résoudre, on peut toujours se poser la question à savoir si on peut le diviser
en deux autres problème (ou en plus), idéalement qui se résolvent indépendamment.
III-Algorithmes ensemblistes
On peut appliquer l’inversion au principe « diviser pour régner », ce qui va donner ce qu’on peut appeler « réunir pour
régner » : c’est l’algorithmique ensembliste. C’est une démarche très importante mais très peu enseignée dans les cours
d’algorithmique.
Problème : Commissions
Si on doit se rendre en route pour acheter un bonbon ; on revient, on va acheter un mouchoir ; on revient, on va
acheter un stylo, c’est énorme ! On aurait pu aller acheter tous les trois éléments au même moment, ca fait moins
d’efforts. On a ainsi rassemblé c à d que au lieu de faire individuellement plusieurs choses, on peut tout simplement les
grouper en un bloc de choses ; plutôt que de faire les choses une à une, on peut tout simplement regrouper certaines
choses et les faire ensemble.
IV-Techniques heuristique
Ca rassemble tout un grand nombre d’algorithmes qui s’appuient sur l’idée selon laquelle le plus important dans la vie
n’est pas de résoudre exactement un problème (il peut être trop couteux et pas forcement rentable de savoir résoudre de
façon exacte un problème) il arrive même que pour certains problèmes, la solution exacte est hors de notre portée.
Ex : Jeux d’échecs
Un ordinateur qui joue aux échecs, s’il cherche à trouver le meilleur coup parmi toutes les autres combinaisons, devra
mettre un temps infini pour trouver cette solution. Il va donc renoncer à chercher ce meilleur coup pour chercher à
trouver un coup efficace en réduisant son espace d’exploration en appliquant des règles : les heuristiques.
Une heuristique est une règle de choix qui nous aide parmi plusieurs cas à déterminer le cas qu’on choisit. Elle ne mène
pas forcement à la meilleure solution mais à une très bonne solution satisfaisante.
Si on veut ranger des affaires dans une valise, une règle heuristique consistera à ranger d’abord les plus grandes affaires
pour terminer par les plus petites.
Il existe plusieurs problèmes dont la complexité combinatoire est infinie, pour ceux là, on ne va pas chercher l’optimum
mais plutôt s’appuyer sur une démarche heuristique.
Une personne peut mémoriser plus de 200 mots à la fois, une autre peut mémoriser uniquement 30 parmi ceux qu’il
utilise fréquemment (il mémorisera d’autres selon leur nécessité). Evidement c’est celui qui n’a mémorisé que 30 qui veux
le mieux s’exprimer.
V-Approche itérative
Dans cette démarche, le problème à résoudre est vu comme une séquence : on prend le premier élément de la séquence,
on le résout et on passe à l’élément suivant, on parcourt ainsi toute la séquence. A la fin, on se rendra compte que tout le
problème est résolu.
Cette approche n’est pas toujours bonne car résoudre 1 000 000 x 1 000 000 serait fastidieux. On peut alors au lieu
d’itérer, diviser le problème, car en divisant on converger plus vite qu’en itérant.
VI-Programmation dynamique
Elle s’applique à des problèmes pour lesquels on cherche le moyen le plus efficace et économique pour parvenir à un
résultat B, à partir d’une situation A. Cette approche va résoudre le problème plutôt en partant de l’arrivée B pour revenir
vers le point de départ A. On démarre à la fin et on revient en prenant à chaque fois la sous séquence optimale, on prend
ce qui est la meilleure solution de toutes les solutions qui aboutissent à une situation jusqu’à revenir au nœud de départ.
Faire de la programmation dynamique c’est résoudre le problème à partir de l’arrivée, c’est une sorte de chainage arrière.
Elle donne toujours la meilleure solution si celle si existe.
VII-Algorithmes gloutons
On quitte du point de départ, on à un point qu’on essaie d’atteindre. On appliquera ainsi des heuristiques à chaque fois.
Par exemple, pour aller de A, B, on peut décider de toujours prendre le plus court chemin pour pouvoir avancer. Mais en
prenant toujours le plus court chemin, on peut avoir un chemin final très long par rapport à un autre qui était direct.
L’algorithme glouton ne donne pas toujours le meilleurs résultat et parfois même ne trouve pas de résultat alors que celui-
ci existe. C’est une approche qui est toujours sur l’idée de la recherche de l’efficace par rapport à l’optimal. Ainsi, si cet
algorithme marche, on obtiendra un bon résultat à un faible coût, mais le plus souvent on n’est pas très loin du bon
résultat.
Un menuisier doit donner des formes à des plaques de verre. Un client passe sa commande avec des dimensions
bien définies. Le menuisier a un stock contenant des plaques de tailles différentes et doit couper la commande du client
dans ces plaques. Comment donc découper ces plaques de verre sans avoir beaucoup de rejets ?
Il peut trier ses plaques par ordre décroissant ainsi que celles de son client. Et associer par exemple les plus grosses
plaques de son client à celles contenues dans son stock jusqu’à la fin.
VIII-Systèmes experts
La démarche des systèmes experts est une démarche qui consiste à donner à l’ordinateur une capacité de conduire des
résonnements logiques. Dès qu’on permet à l’ordinateur de conduire des résonnements logiques (à l’aide d’un logiciel : le
moteur d’inférence) et qu’on lui donne ensuite une base des règles (base définissant les règles selon lesquelles il va faire
ses déductions dans un domaine bien précis). A l’aide d’un générateur de système expert, on peut dire à l’ordinateur de
résoudre un problème en lui présentant uniquement des faits et il va réfléchir comme un homme pour arriver à des
solutions.
IX-Démarche probabiliste
Les algorithmes probabilistes se basent sur le fait que chaque fois que la résolution exacte d’un problème et très
couteuse, et qu’on a le moyen de résoudre de façon, approché le problème par les probabilités, alors on utilise un
algorithme probabilisé.
Ex : Taille moyenne
Pour avoir la taille moyenne des étudiants du 3GI, on peut mesurer tout le monde et faire la moyenne ou alors on peut
juste prélever un échantillon des étudiants, on fait des mesures et à l’aide des probabilités, on généralise le résultat à tous
les étudiants
Quand on veut étudier des phénomènes aléatoires ou alors si on souhaite créer le hasard :
X-Simulations
Son principe est d’essayer de créer dans l’ordinateur via notre algorithme, quelque chose qui et représentatif de la réalité.
On mène une expérience dans l’ordinateur (dans le virtuel) et les résultats obtenus représentent les résultats qu’on aurait
obtenu dan la vie réelle.
Problème : La famille
Une famille est constituée de n personnes qui s’asseyent tous les jours sur n chaises mais le font tout au hasard.
En moyenne après combien de temps chaque membre de la famille s’est assis sur toutes les n chaises ?
XI-Algorithmes génétiques
C’est un cas particulier de la démarche de simulation ; son principe est d’utiliser les règles de la génétique pour
fonctionner. Ces algorithmes vont essayer de travailler sur une population avec des individus ; pour savoir ce qui va se
passer ou pour avoir la meilleure solution à un problème, on peut appliquer les opérations de la génétique sur la
population (croisement de deux individus, mutation, destruction), on va ainsi faire évoluer la population vers un état
d’équilibre qui représente très souvent la solution à notre problème.
XII-Les réseaux de neurones
Ils représentent une démarche presque similaire à l’algorithmique génétique, on essaie d’imiter le vivant. Ainsi, on va
essayer de faire des algorithmes qui fonctionnement comme on pense que les neurones humains fonctionnent. Donc on
aura des petits blocs (neurones), chaque neurone pouvant entretenir des connexions avec d’autres neurones. Chaque
neurone a des entrées et a une sortie au moins qui envoie des résultats ou qui transfert des informations. Ainsi, on va lui
envoyer un bloc d’information (vecteur représentant les informations à traiter), à chacune des composantes du vecteur il
attribue un poids (coefficient d’importance entre 0 et 1) puis il a une fonction de transition disant que le poids global de
l’information reçu est sous forme Wi Xi où Wi est le poids de la composante Xi du vecteur d’information entré en
paramètre et sur cette information, il va appliquer une fonction de transfert g et en fonction du résultat obtenu, il va soit
envoyer un signal à la sortie, soit ne rien envoyer ; la sortie pouvant être l’entré d’un autre neurone.
Cette démarche est utilisée très souvent pour effectuer la classification (reconnaissance faciale, de caractère, etc.), la
reconnaissance partielle d’image,…
Quand on a un problème à résoudre, on n’est pas obligés de le résoudre sous sa forme originale, on peut décider le
transformer sous une autre forme pour mieux parvenir au résultat.
Toujours se poser la question : est ce qu’il n y a pas une autre façon de représenter mon problème, de structurer,
d’organiser, d’ordonner les données de mon problème, est ce que je n’ai pas une autre façon de le faire qui rende mon
problème plus facile à résoudre ?
Est-ce que je ne peux pas par une transformation arriver à un autre problème facile à résoudre (en terme de complexité
algorithmique : beaucoup moins de temps et d’opération) ;
Le multi-niveau intervient au niveau de complexités ; on ne compare pas des opérations à des niveaux de complexité
différents. Ce problème de complexité intervient plus quand on travaille sur le BD, les fichiers, le réseau à distance, les
niveaux de complexité sont très élevés, il faut tout faire pour remmener cela au niveau mémoire qui et le meilleur niveau
de complexité.
Elle consiste à écrire des équations ou des systèmes mathématiques qui rendent compte du problème à résoudre. Une
fois le modèle fait, on peut soit le résoudre analytiquement, soit écrire des algorithmes selon le autres modèles
précédents afin de le résoudre.
XV-Autres
Ce sont les choses qu’on n’a pas vu ici et qu’on peut inventer. Donc si les autres méthodes n’ont pas marché, on peut
toujours se dire qu’il y’a d’autres méthodes.