- Tutoriel sur le codage de Huffman
- Exercices corrigés sur les structures de contrôle et les structures de données
- Exercices corrigés sur la complexité en temps
- Corrected exercises about time complexity (en)
- Exercices corrigés sur les algorithmes récursifs, terminaux, multiples et croisés
- Exercices corrigés de type Licence sur le paradigme de diviser pour régner
- Exercices corrigés sur les algorithmes en Diviser pour régner et Programmation dynamique
- Corrected exercises about divide & conquer and dynamic programming (en)
- Exercice corrigé pas à pas du Branch and Bound sur du LP en nombre entier
- Exercices corrigés de programmation logique par contraintes
- Exercices corrigés sur les algorithmes de tri
Algorithmique
L’algorithmique existe depuis toujours, il s’agit d’un processus de pensée décrit de manière logique. Bien que ce système nous semble aujourd’hui indispensable pour nombres de sciences, la systématisation de l’écriture algorithmique a évolué au cours du temps et des technologies. Elle a commencé du temps des babyloniens, jusqu’à être concrètement établi par René Descartes dans la méthode générale proposée par le Discours de la méthode en 1637.
L’algorithmique moderne, comprenant un langage dit de « programme » fait ses débuts peu de temps après en 1677. Le terme que l’on utilise de nos jours, « algorithme », apparaît quant à lui deux siècles plus tard.
L’algorithmique du XXe et du XXIe siècle se base souvent sur des formalismes comme celui des machines de Turing, qui donne un cadre scientifique pour étudier les propriétés des algorithmes.
Avec l’informatique, l’algorithmique s’est beaucoup développée dans la deuxième moitié du XXe siècle et Donald Knuth, auteur du traité The Art of Computer Programming a posé des fondements mathématiques rigoureux de leur analyse.
De nombreux outils formels ou théoriques ont été développés pour décrire les algorithmes, les étudier, exprimer leurs qualités, pouvoir les comparer :
- des structures algorithmiques : structures de contrôle et structures de données.
- les notions de correction, de complétude et de terminaison.
- la théorie de la complexité.
Structure de contrôle et structure de données
On appelle aussi cet enchaînement d’instructions le flot d’exécution d’un programme et on peut le représenter à l’aide d’un graphe de flot de contrôle ou un automate. Certain paradigme de programmation faisant appel à plusieurs processeur s’expose alors au problème d’affectation des tâches dans les processeurs.
Chaque langage informatique possède un type de structure de contrôle et structure de données. L’écriture d’un algorithme se base très souvent sur des langages très répandus tels que le C, le java, etc.
Notions de terminaison, de correction, de complétude
La terminaison est l’assurance que l’algorithme terminera en un temps fini. Les preuves de terminaison font habituellement intervenir une fonction entière positive strictement décroissante à chaque étape/itération de l’algorithme.
Étant donnée la garantie qu’un algorithme terminera, la preuve de correction doit apporter l’assurance que si l’algorithme termine en donnant une proposition de solution, alors cette solution est correcte (dans le sens où elle répond au problème posé).
La preuve de complétude garantit que, pour un espace de problèmes donné, l’algorithme, s’il termine, donnera une solution pour chacune des entrées de l’algorithme.
Terminaison : l’algorithme possède une complexité en temps.
Correction : toute réponse calculée de l’algorithme est solution du problème.
Complétude : l’algorithme peut calculer une réponse pour toute instance du problème.
Complexité algorithmique
algorithme : la performance « naturelle » d’un algorithme en dehors de l’environnement dans lequel sera implémenté ce dernier.
Il existe plusieurs types d’analyse de la performance d’un algorithme :
- L’analyse optimiste (analyse dans le cas le plus favorable ou analyse dans le meilleur des cas).
- L’analyse en moyenne est souvent facteur du paradigme de programmation utilisé.
- L’analyse pessimiste (analyse dans le cas le plus défavorable ou analyse dans le pire des cas).
Les classes de complexité sont des ensembles de problèmes qui ont la propriété d’avoir tous la même complexité selon un certain critère. Les classes les plus connues sont des classes définies sur des machines de Turing (déterministes ou non déterministes – voir le cours sur les automates) avec des contraintes de temps et d’espace. Il existe une relation entre la complexité algorithmique et son coût énergétique de fonctionnement, appelé principe de Landauer.
Voici une liste des complexités les plus fréquemment rencontrées :
Notation | Type de complexité |
---|---|
![]() | complexité constante : une affectation, un calcul élémentaire, etc. |
![]() | complexité logarithmique : dichotomie, arbre |
![]() | complexité linéaire : une boucle |
![]() | complexité quasi-linéaire : diviser pour régner, arbre |
![]() | complexité quadratique : imbrication deux boucles |
![]() | complexité cubique : imbrication de trois boucles |
![]() | complexité polynomiale : imbrication de boucles sans connaissance d’états |
![]() | complexité quasi-polynomiale : diviser pour régner |
![]() | complexité exponentielle : arbre, force brute |
![]() | complexité factorielle : approche naïve d’énumération combinatoire |