INF 111 - Introduction À L'algorithmique 2021

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 42

Introduction à

l’algorithmique
ATSA ETOUNDI Roger, Professeur
[email protected]
Etapes de développement des logiciels
• Identification et Compréhension du problème
• Ingénierie des besoins
• Définition du cahier de charges

• Planification
• Identification des différentes ressources inhérentes au développement
• Définition des différentes contraintes
• Définition de l’ordonnancement des activités associées aux ressources
• Programmation des activités

• Définition de la démarche de résolution du problème


• Conception de la solution
• Solution globale
• Approches de definition des algorithmes
• Definition de l’architecture du logiciel
• Solution détaillée
• Définition des structures de données
• Tableaux
• Vecteur
• matrice
• Définition des algorithmes
• Ecriture des instructions ou commandes pour atteindre le résultat voulu
• Connaitre les structures de contrôle
• Structures repetitives
• Exemples de queques algorithmes claisiques
• Algorithmes de tri
• Analyse des algorithmes
Etapes de développement des logiciels
• Création de contenu
• Identification des acteurs pouvant fournir les données réelles
• Recherche des données réelles relative a la gestion du problème

• Développement/codification des algorithmes

• Choix du paradigme de programmation


• Choix du langage de programmation.
• Tests.
• Déploiement et maintenance.
Techniques de conception d’algorithmes
• Algorithme de glouton
• Diviser pour régner
• Programmation dynamique
Algorithme de glouton
• 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.
Algorithme de glouton: Le principe
• 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:
• en espérant obtenir une solution optimale en effectuant une suite de choix : à
chaque étape on fait le meilleur choix local
• Pas de retour en arrière : à chaque étape de décision dans l’algorithme, le
choix qui semble le meilleur à ce moment est effectué.
• Progression descendante : choix puis résolution d’un problème plus petit
Exemple: Le monnayeur
• On dispose des pièces des monnaies correspondant aux valeurs P =
{25,25,25,10,10,5,1,1,1,1}
• montant à payer (n = 67).
• Sortie: ensemble des pièces utilisées (S = {25,25,10,5,1,1}), le moins
de pièces possibles.
• Etant donnée une quantité c entière, on veut trouver une façon de
"rendre" la somme c avec un nombre de pièces minimum.
• Construction de la solution:
• S={}; s={25}, s={25}u{25}, s={25,25}u{10}; s={25,25,10}u{5};
s={25,25,10,5}u{1}; s={25,25,10,5,1}u{1}
Stratégie
• ajouter la plus grande pièce possible
• tant que la somme n’excède pas le montant à payer
Exercice
1. En utilisant l’approche gloutonne, donner la solution au problème
de remplissage d’un sac dont le poids maximal est connu avec les
objets ayant chacun un poids. La contrainte étant que le sac doit
avoir le plus d’objets possible
2. En utilisant l’approche gloutonne, donner la solution au problème
de remplissage d’un sac dont le poids et le volume maximal sont
connus avec les objets ayant chacun un poids et un volume. La
contrainte étant que le sac doit avoir le plus d’objets possible
Diviser pour régner
• 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é :
• Diviser : le problème en sous-problèmes plus petits
• Régner : sur les sous-problèmes en les résolvant récursivement ou, si la taille
d’un sous-problème est assez réduite, le résoudre directement ;
• Combiner : les réponses des sous-problèmes afin d'obtenir la réponse au
problème de départ
Attention lors de la composition
• La solution S3 vérifiant les propriétés P3 est issue de S1 vérifiant P1 et
de S2 vérifiant p2
• Il existe un homomorphisme h: S1xS2 -> S3 ou h: S2xS1 -> S3
• P3 = P1uP2uP3’ avec P3’ les propriétés vérifiées exclusivement par S3.
Programmation dynamique
• 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.).
• 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.
Programmation dynamique
• 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.
Spécification d’un algorithme
• (Nm, De, Ds, Aut, Pde, PDs)
• Nm: dénote le nom de l’algorithme
• De: dénote les données en entrée
• Ds: dénote le données en sortie
• PDe: dénote les propriétés devant être vérifiées par De
• PDs: dénote les propriétés devant être vérifiées par Ds
• Aut: dénote l’automate qui transforme les De en Ds
Structures de données
• Structures de données de base
• Structures de données évoluées
• Structures de données dynamiques
Structure de donnees de base
• Les entiers: 0,1,2, …, n, n+1
• Les nombres relatifs
• Les réels,
• Booléens,
• bit
• Caractère
• Chaine de caractères
Type abstrait de donnée
• Un type abstrait de donnée est un représentation formelle d’un type de
données
• Représentation est dite formelle car elle utilise les concepts
mathématiques
• Elle est définie par
• Son nom
• Son type d’interet
• Les opérations
• Générateurs
• modification
• Constructeurs
• Observateurs
• predicats
• Les propriétés
Type Booléen
TAD Bool1
Tyepe: Bool
Generateur
TAD Bool2
true:Bool
false:Bool étendre Bool1 avec
Constructeurs Constructeur
et: Bool xBool -> Bool non: Bool -> Bool
ou : Bool x Bool -> Bool
Propriété
eq : Bool x Bool -> Bool
Propriétés P3: forall b:Bool non (non b))=b
P1: forall b:Bool b et b =b fin
p2: forall b,b’:Bool, b=/=b’ => b eq b’ = false
fin
Type abstrait des entiers naturels
TAD Nat0
Type Nat
utilise Bool
Generateur
0:Nat
1:Nat
Constructeur
succ : Nat -> Nat
Propriété
P1: forall n:nat Succ(n) = N+1
p2: succ(0) = 1
fin
Type chaine de caractères
TAD Ch1
Type: Ch, Char
utilise Nat
Générateur
chv:Ch
Constructeurs
concat: Ch x Ch -> Ch
sousch: ChxNatxNat -> Nat
long: Ch -> Nat
souschg: Ch x Nat -> Ch
souschd ChxNat -> Ch
observateur
char: ChxNat -> Char
Agenda
• Les algorithmes classiques de Tri
• Tris stables
• Le tri par insertion
• Le tri bulle
• Le tri Shaker
• Le tri Gnome
• Le tri fusion
• Tri non stable
• Tri rapide
• Le tri par sélection
• Le tri Shell
• Le tri maximier
• Le tri à peigne
Problématique du Tri
• On désigne par "tri" l'opération consistant à ordonner un ensemble
d'éléments en fonction de clés/poids/valeur sur lesquels est définie une
relation d'ordre.
• Les algorithmes de tri ont une grande importance pratique. Ils sont
fondamentaux dans certains domaines, comme l'informatique de
gestion où l'on tri de manière quasi-systématique des données avant de
les utiliser.
• L'étude du tri est également intéressante en elle-même car il s'agit sans
doute du domaine de l'algorithmique qui a été le plus étudié et qui a
conduit à des résultats remarquables sur la construction d'algorithmes
et l'étude de leur complexité.
Le tri par insertion
• On fait comme si les éléments à trier étaient donnés un par un, le premier
élément constituant, à lui tout seul, une liste triée de longueur 1. On range
ensuite le second élément pour constituer une liste triée de longueur 2, puis
on range le troisième élément pour avoir une liste triée de longueur 3 et
ainsi de suite...
• Le principe du tri par insertion est donc d'insérer à la nième itération le
nième élément à la bonne place.

Pseudo code associé à la description de l’agorithme

PROCEDURE tri_Insertion ( Tableau a[1:n])


POUR i VARIANT DE 2 A n FAIRE
INSERER a[i] à sa place dans a[1:i-1];
FIN PROCEDURE;

Devoir: Développer un simulateur de cet algorithme en s’appuyant sur les technologies


Le tri par sélection
• Le principe du tri par sélection/échange (ou tri par extraction) est
d'aller chercher le plus petit élément du vecteur pour le mettre en
premier, puis de repartir du second élément et d'aller chercher le plus
petit élément du vecteur pour le mettre en second, etc..

Pseudo code associé


PROCEDURE tri_Selection ( Tableau a[1:n])
POUR i VARIANT DE 1 A n - 1 FAIRE
TROUVER [j] LE PLUS PETIT ELEMENT DE [i + 1:n];
ECHANGER [j] ET [i];
FIN PROCEDURE;
Le tri bulle

Le principe du tri à bulles Pseudo code associé au principe


(bubble sort ou sinking sort) PROCEDURE tri_bulle ( TABLEAU a[1:n])
est de comparer deux à deux passage ← 0
les éléments e1 et REPETER
e2 consécutifs d'un tableau et permut ← FAUX
d'effecteur une permutation si POUR i VARIANT DE 1 A n - 1 - passage FAIRE
SI a[i] > a[i+1] ALORS
e1 > e2. echanger a[i] ET a[i+1]
permut ← VRAI
FIN SI
On continue de trier jusqu'à FIN POUR
ce qu'il n'y ait plus de passage ← passage + 1
TANT QUE permut = VRAI
permutation. Fin procedure
Le tri à peigne

• Le tri à peigne est un algorithme de tri par comparaison qui améliore


de façon notable les performances du tri à bulle. Cet algorithme fut
conçu en 1980 par Włodzimierz Dobosiewicz. Quelques années plus
tard, en 1991, Stephen Lacey et Richard Box ont montré dans un
article dans Byte Magazine que l'idée de Donald Shell pouvait
s'appliquer également, et avec autant de bénéfices, au tri bulle.
• Le principe est de ne plus comparer uniquement des éléments
adjacents, mais de commencer par comparer des éléments plus
lointains, puis de raccourcir progressivement l'intervalle entre les
éléments pour aboutir finalement à un tri à bulle classique.
Le tri à peigne
PROCEDURE tri_peigne ( TABLEAU a[1:n])
gap ← n
REPETER
permut ← FAUX
gap ← gap / 1.3
SI gap < 1 ALORS gap ← 1
POUR i VARIANT DE 1 A n AVEC UN PAS gap FAIRE
SI a[i] > a[i+gap] ALORS
echanger a[i] et a[i+gap]
permut ← VRAI
FIN SI
FIN POUR
TANT QUE permut = VRAI OU gap > 1
Fin procedure
Le tri shaker
• Le tri "Shaker", également appelé tri "Cocktail", tri "Shuttle",
tri "boustrophédon" ou tri à bulles bidirectionnel est une variante du tri
à bulles.
• Son principe est identique à celui du tri à bulles, sauf qu'il change de
direction à chaque passe.
• C'est une légère amélioration car il permet non seulement aux plus
grands éléments de migrer vers la fin de la série mais également aux
plus petits éléments de migrer vers le début.
Le tri shaker
PROCEDURE tri_shaker ( TABLEAU a[1:n])

sens ← 'avant', debut ← 1, fin ← n-1, en_cours ← 1 TANT


QUE ((sens='avant') ET (en_cours<fin)) OU ((sen
REPETER s='arriere) ET (en_cours>debut))
permut ← FAUX SI (sens='avant') ALORS
REPETER sens ← 'arriere'
SI a[en_cours] > a[en_cours + 1] ALORS fin ← fin - 1
echanger a[en_cours] et a[en_cours + 1] SINON
permut ← VRAI sens ← 'avant'
FIN SI debut ← debut + 1
SI (sens='avant') ALORS FIN SI
en_cours ← en_cours + 1 TANT QUE permut = VRAI
SINON
en_cours ← en_cours - 1 FIN PROCEDURE
FIN SI
Le tri de Shell

• Donald L. Shell proposa, en 1959, une variante du tri par insertion. Ce


tri consiste à trier séparément des sous-suites de la table, formées par
les éléments répartis de h en h.
• Empiriquement, Shell propose la suite d'incréments vérifiant h1 = 1,
hn+1 = 3hn+1 en réalisant les tris du plus grand intervalle possible vers
le plus petit.
Le tri de Shell
PROCEDURE tri_Insertion ( Tableau a[1:n],gap,debut)
POUR i VARIANT DE debut A n AVEC UN PAS gap FAIRE
INSERER a[i] à sa place dans a[1:i-1];
FIN PROCEDURE;

PROCEDURE tri_shell ( Tableau a[1:n])


POUR gap DANS (6,4,3,2,1) FAIRE
POUR debut VARIANT DE 0 A gap - 1 FAIRE
tri_Insertion(Tableau,gap,debut);
FIN POUR;
FIN POUR;
FIN PROCEDURE
Le tri Gnome
• Cet algorithme a été d'abord proposé en 2000 - sous le nom de "tri
stupide" - par le Dr. Hamid Sarbazi-Azad (Professeur à l'université de
Sharif, une des plus grandes universités d'Iran) puis redécouvert plus
tard par Dick Grune (le premier développeur de CVS) qui l'appela
"gnome sort" (parce qu'il parait que c'est la méthode qu'utilisent les
nains de jardin hollandais pour trier une rangée de pots de fleurs).
• L'algorithme est similaire au tri par insertion, sauf que, au lieu de
insérer directement l'élément à sa bonne place, l'algorithme effectue
une série de permutations, comme dans un tri bulle.
Le tri Gnome
PROCEDURE tri_Gnome(tableau[])
pos ← 1
TANT QUE pos < longueur(tableau)
SI (tableau[pos] >= tableau[pos-1])
pos ← pos + 1
SINON
echanger tableau[pos] ET tableau[pos-1]
SI (pos > 1)
pos ← pos - 1
FIN SI
FIN SI
FIN TANT QUE
FIN PROCEDURE
Le tri maximier
• Cette méthode de tri (aussi appelée «tri par tas» ou «heapsort» ou «tri
de Williams») est basée sur la notion de tas. Un tas est un arbre binaire
parfait tel que l’information contenue dans tout nœud est supérieure à
celle contenue dans ses fils. La méthode du tri par tas comporte deux
étapes :
• Construction par insertions successives d’un tas à partir du vecteur à
trier.
• On remplace la racine, qui est nécessairement le plus grand élément du
tableau par son fils le plus grand. La racine est transférée à la place de
la dernière feuille de l’arbre et celle-ci est repositionnée. On réitère
avec la nouvelle racine autant de fois qu’il y a de nœuds dans l’arbre.
Le tri maximier
Le tri fusion
• Il s’agit à nouveau d’un tri suivant le paradigme diviser pour régner. Le
principe du tri fusion (ou tri par interclassement) en est le suivant :
• On divise en deux moitiés la liste à trier (en prenant par exemple, un élément
sur deux pour chacune des listes).
• On trie chacune d’entre elles.
• On fusionne les deux moitiés obtenues pour reconstituer la liste triée.
Le tri fusion
PROCEDURE tri_fusion ( TABLEAU a[1:n])
FAIRE
SI TABLEAU EST VIDE RENVOYER TABLEAU
gauche = partie_gauche de TABLEAU
droite = partie_droite de TABLEAU
gauche = tri_fusion gauche
droite = tri_fusion droite
renvoyer fusion gauche droite
POUR i VARIANT DE 1 A n - 1 - passage FAIRE
SI a[i] > a[i+1] ALORS
echanger a[i] ET a[i+1]
permut ← VRAI
FIN SI
FIN POUR
passage ← passage + 1
FIN PROCEDURE
Le tri rapide
• Le tri rapide - aussi appelé "tri de Hoare" (du nom de son inventeur Tony Hoare)
ou "tri par segmentation" ou "tri des bijoutiers" ou, en anglais "quicksort" - est
certainement l’algorithme de tri interne le plus efficace.
• Le principe de ce tri est d’ordonner le vecteur T.(0)..T.(n) en cherchant dans celui-
ci une clé pivot autour de laquelle réorganiser ses éléments. Il est souhaitable que
le pivot soit aussi proche que possible de la clé relative à l’enregistrement central
du vecteur, afin qu’il y ait à peu près autant d’éléments le précédant que le suivant,
soit environ la moitié des éléments du tableau. Dans la pratique, comme dans la
démo ci-dessous, on prend souvent le dernier élément du tableau.
• On permute ceux-ci de façon à ce que pour un indice j particulier tous les éléments
dont la clé est inférieure à pivot se trouvent dans T.(0)...T.(j) et tous ceux dont la
clé est supérieure se trouvent dans T.(j+1)...T.(n). On place ensuite le pivot à la
position j.
• On applique ensuite le tri récursivement à, sur la partie dont les éléments sont
inférieurs au pivot et sur la partie dont les éléments sont supérieurs au pivot.
Le tri rapide
• Le choix du pivot est déterminant pour l'efficacité de ce tri. Plusieurs
options sont possibles :
• Choisir le premier élément du tableau
• Choisir le dernier élément du tableau
• Choisir un élément au hasard
• Choisir l'élément au milieu du tableau
• Trouver le pivot optimal en recherchant la médiane
• Ces différentes options peuvent être testées avec l'application ci-
dessous. Choisir la médiane comme pivot est bien entendu la solution
optimale... sauf que, la recherche de cette médiane est elle-même
coûteuse.
Le tri rapide
Procedure tri_rapide (tableau [1:n], gauche, droit )
DEBUT
(* mur marque la separation entre les elements plus petits et ceux plus grands que
pivot*)
mur ← gauche;
(* On prend comme pivot l element le plus a droite *)
pivot ← tableau[droit];
placer a gauche de mur tout les elements plus petits
placer a droite de mur tout les element plus grands
(* On place correctement le pivot *)
placer le pivot a la place de mur
(* On poursuit par recursivite *)
SI (gauche<mur-1) ALORS tri_rapide(tableau,gauche,mur-1);
SI (mur+1<droit) ALORS tri_rapide(tableau,mur,droit);
FIN procedure

Vous aimerez peut-être aussi