Upload
uh1
View
1
Download
0
Embed Size (px)
Citation preview
1
EL BAHRI Tahar
ALGORITHMES AVANCES
Tri par différents structures de données
2
Mr. Imad HAFIDI
Remerciement
Avant d’entamer ce rapport, mes remerciements s’adressent en premier lieu
à mon encadrant Mr. Imad HAFIDI qui nous a formé et accompagné tout au
long de la préparation de ce projet avec beaucoup de patience et de pédagogie.
Qu’il retrouve ici mes profondes gratitudes pour leur disponibilité, leurs
directives précieuses et leur aide durant notre formation. Je les remercie aussi
pour leur patience, leur dévouement permanent, leurs conseils pertinents et leur
encadrement direct et amical de ce projet sans lequel ce travail n’aurait pas
abouti.
Je remercie aussi très sincèrement mes camarades de classe qui m’ont aidé
- de près ou de loin - pour terminer ce travail.
3
Contexte du projet
Dans le cadre du module d’algorithmes avancées, et après avoir acquis des
connaissances approfondies en algorithmique et langage C, nous avons été amené
à réaliser un simulateur de tri en utilisant différents structures de données vues en
cours : Tableau, Liste chainées, Arbres binaire de recherche, AVL, Tas ….
Problématique de tri
Depuis l’avènement de l’informatique, les ordinateurs sont capables de traiter
des quantités d’informations de plus en plus importantes. Actuellement, un
simple ordinateur de bureau n’a rien à envier aux gros ordinateurs à peine plus
âgés qu’eux. Mais la capacité des ordinateurs à effectuer des traitements de plus
en plus importants n’est pas uniquement due à l’évolution physique des
machines.
Le traitement de données de masse pose le problème de leur classement. C’est
pour cela que différentes méthodes de tris ont été développées. L’étude des tris
est un problème intéressant puisque c’est l’un des domaines de l’algorithmique
qui a été le plus étudié. Cette étude permet également d’aborder de façon
concrète les problèmes de complexité des algorithmes. Ainsi, pour un problème
simple et unique, le tri d’un tableau de données, de nombreuses solutions existent.
Malheureusement, seules quelques-unes d’entre elles sont assez performantes
pour supporter le traitement d’un nombre élevé de valeurs.
5
Chapitre I : Structure de données
Une table est une structure de données telle que l’accès à un élément est déterminé à partir
de sa clé. La clé permet d’identifier un élément de manière unique, la clé (un entier ou une
chaîne alphanumérique) est dite discriminante. Dans la suite de ce chapitre, on n’envisage
pas les cas où une même clé peut correspondre à plusieurs éléments. Connaissant la clé,
on peut retrouver l’élément et ses caractéristiques. L’allocation d’espace pour une table est
souvent contiguë. Il faut réserver l’espace mémoire en début de traitement (en mémoire
centrale ou sur mémoire secondaire).
Méthodes de tri
1. Tri par sélection
Définition et caractéristiques
6
Le principe du tri par sélection est le suivant. On sélectionne le maximum (le plus grand)
de tous les éléments, et on le place en dernière position n-1 par un échange. Il ne reste plus
qu’à trier les n-1 premiers éléments, pour lesquels on itère le procédé.
Exemple :
Grandes étapes de l’évolution du tableau au fil de l’algorithme.
En bleu, les valeurs déjà traitées.
Algorithme :
2. Tri par insertion
Le principe du tri par insertion est le suivant : on trie d’abord les deux premiers éléments,
puis on insère le 3ème à sa place pour faire une liste triée de 3 éléments, puis on insère le
4ème élément dans la liste triée. La liste triée grossit jusqu’à contenir les n éléments.
Exemple :
Grandes étapes de l’évolution du tableau au fil
de l’algorithme. En bleu, le tableau trié, en rouge,
la valeur de la mémoire qui contient la valeur
à insérer.
7
Algorithme :
3. Tri par fusion
Le tri fusion est construit suivant la stratégie "diviser pour régner", en anglais "divide and
conquer". Le principe de base de la stratégie "diviser pour régner" est que pour résoudre un
gros problème, il est souvent plus facile de le diviser en petits problèmes élémentaires.
Une fois chaque petit problème résolu, il n’y a plus qu’à combiner les différentes solutions
pour résoudre le problème global. La méthode "diviser pour régner" est tout à fait
applicable au problème de tri : plutôt que de trier le tableau complet, il est préférable de
trier deux sous tableaux de taille égale, puis de fusionner les résultats.
Exemple :
Grandes étapes de l’évolution du
tableau au fil de l’algorithme :
8
Algorithme :
algorithme TRI-FUSION(@T,g,d);
données
T: tableau de valeurs;
g,d: entiers;
variables
p: entier;
debut
SI (g < d) ALORS
p ← (g + d) / 2;
TRI-FUSION(T,g,p);
TRI-FUSION(T,p + 1,d);
FUSIONNER(@T,g,p,d);
FSI
fin.
4. Tri rapide
L’algorithme de tri rapide, "quick sort" en anglais, est un algorithme de type
dichotomique. Son principe consiste à séparer l’ensemble des éléments en deux parties. La
différence par rapport au tri fusion, vu précédemment, est que la séparation des différentes
valeurs ne s’effectue pas n’importe comment. Pour effectuer la séparation, une valeur pivot
est choisie. Les valeurs sont réparties en deux ensembles suivant qu’elles sont plus grandes ou
plus petites que le pivot. Ensuite, les deux ensembles sont triés séparément, suivant la même
méthode.
Exemple :
Grandes étapes de l’évolution du tableau au
fil de l’algorithme : En bleu, les valeurs déjà
positionnées, en rose, les valeurs qui servent
de pivot pour passer à la ligne suivante.
9
Algorithme :
5. Tri par shell
Le tri par insertion provoquait le décalage de tous les éléments plus grands que l’élément à
insérer. Dans le tri Shell, les éléments ne sont pas décalés d’un élément à la fois, mais de
plusieurs éléments, dont la différence d’indice est appelée "pas". Ainsi, à chaque étape, le tri
est dégrossit puis le pas est réduit. Chaque réduction de pas provoque un affinage du tri.
Lorsque le pas atteint la valeur 1, cela revient à effectuer le tri par insertion.
Cependant, cette fois, le tri par insertion est appliqué à un tableau possédant un certain
ordre (provoqué par les étapes de préparations où le pas est supérieur à un). En effet, les
différentes étapes où le pas est supérieur à un provoque le regroupement des différentes
valeurs par groupes de la même taille que le pas.
10
Exemple :
Évolution du tableau au fil du tri shell. Le pas,
représenté en rouge est également indiqué ainsi
que la valeur en mémoire, sur laquelle porte la
comparaison. En bleu, les valeurs sur lesquels
portent les comparaisons à chaque étape.
Algorithme :
Une pile est une structure de données dans laquelle on peut ajouter et supprimer des
éléments suivant la règle du dernier arrivé premier sorti ou encore LIFO (Last In First Out).
Une file est une structures de données dans laquelle on peut ajouter et supprimer des
éléments suivant la règle du premier arrivé premier sorti, ou encore FIFO (First In First
Out).
Définition et caractéristiques
11
Définition et caractéristiques
Une liste chaînée (voir figure 19.1) est un ensemble de cellules liées entre elles par des
pointeurs. Chaque cellule est une structure contenant les champs suivants :
• une ou plusieurs données comme dans n’importe quelle structure
• un pointeur suivant sur la cellule suivante
On accède à la liste par un pointeur L sur la première cellule, puis en parcourant la liste
d’une cellule à l’autre en suivant les pointeurs suivant. Le dernier pointeur suivant vaut
NULL, ce qui indique la fin de la liste.
Méthodes de tri
12
Définition et caractéristiques
Un arbre est une structure de données composée d’un ensemble de nœuds.
Chaque nœud contient l’information spécifique de l’application et des pointeurs vers d’autres
nœuds (d’autres sous-arbres).
Un arbre binaire est un arbre ordonné tel que chaque nœud a au plus deux fils et quand il n’y
en a qu’un, on distingue le fils droit du fils gauche.
C'est un des arbres les plus simples, et nous allons le simplifier au maximum. Ses éléments
(ou nœuds) ne contiendront qu'une valeur de type entier.
Méthodes de tri
Le tri par Arbre Binaire de Recherche est un tri classé à part, non pas parce qu’il est plus
performant, mais parce qu’il nécessite quelques connaissances sur une structure particulière
appelée "arbre". Un arbre est une structure composée d’une racine et plusieurs pointeurs
vers d’autres arbres ou vers une feuille. Une feuille est un arbre particulier qui ne possède
aucun sous arbre, c’est un arbre terminal. Un nœud est la racine d’un sous arbre. L’exemple
ci-dessous illustre le vocabulaire qui viens d’être décrit.
Dans les tris précédents, nous avons déja eu l’occasion de
manipuler une structure de type "arbre". Il s’agit des listes,
qui sont une forme d’arbre particuliére puisque chaque
noeud n’est rattaché qu’à un seul sous arbre : une liste est
une structure comportant une valeur et un pointeur vers
une autre liste.
Les arbres qui nous intéressent ici sont appelés arbres
binaires de recherches (ou ABR). "binaire" car ils ne
peuvent posséder que deux sous arbres et "de recherche" car les valeurs situées dans le sous
arbre gauche d’un ABR sont toutes inférieures à la valeur du nœud de l’arbre, et celles
situées dans le sous arbre droit lui sont supérieures. Construction de l’arbre binaire de
recherche :
Pour réaliser ce tri il faut tout d’abord construire l’arbre binaire de recherche
correspondant aux éléments à classer. C’est ce qui va être fait ici. La première valeur de
13
l’ensemble fera office de racine. Ensuite, pour construire l’arbre binaire, il faut descendre
dans l’arbre en comparant les différents éléments à la racine.
Définition et caractéristiques
Un tas est un tableau A qui peut être vu comme un arbre binaire presque complet. Chaque
nœud de l’arbre correspond à un élément du tableau qui contient la valeur du nœud.
L’arbre est complétement rempli à tous les niveaux, sauf, parfois, sur le plus bas, rempli à
partir de la gauche, jusqu‘`a un certain point.
Méthodes de tri
L’algorithme du tri par tas commence par utiliser CONSTRUIRE-TAS-MAX pour
construire un tas max à partir du tableau A[1 . . n], où n = longueur[A]. Comme l’élément
maximal du tableau est stocké à la racine A[1], on peut le placer dans sa position finale
correcte en l’échangeant avec A[n]. Si l’on « ôte » à présent le nœud n du tas (en
décrémentant taille[A]), on observe que A[1 . . (n − 1)] peut facilement être transformé en tas
max. Les enfants de la racine restent des tas max, mais la nouvelle racine risque d’enfreindre
la propriété de tas max. Pour restaurer la propriété de tas max, il suffit toutefois d’appeler
une seule fois ENTASSER-MAX(A, 1) qui laisse un tas max dans A[1 . . (n − 1)].
L’algorithme du tri par tas répète alors ce processus pour le tas max de taille n − 1 jusqu’à
arriver à un tas de taille 2.
14
Définition et caractéristiques
Un arbre AVL (Adelson-Velskii-Landis) est un arbre binaire de recherche H-équilibré. En
tant qu'arbre binaire de recherche, on peut utiliser l'algorithme des arbres binaires de
recherche pour la recherche ; il aura une complexité de , vu la propriété.
Pour l'insertion, on procèdera comme pour un arbre binaire classique) ; ensuite, on
rétablira l'invariant au besoin à l'aide de rotations.
Méthodes de tri
On peut utiliser un arbre AVL pour le tri : on insère successivement les éléments dans
l'arbre et on effectue un parcours en ordre. On aura une complexité temporelle optimale
mais une complexité en espace linéaire (on doit allouer un arbre).
Chapitre 11 : Conception du Programme
L’application de tri qu’on réaliser en langage C contient pour chaque structure de données
un fichier .h qui représente sa structure et ses fonctions et un fichier .c qui contient un menu
de cette structure et qui implémente ses fonctions.
Un fichier de simulation .c (main.c) qui contient le menu principal de l’application cette
dernière demande à l’utilisateur de choisir la structure de données pour la simulation :
Le menu principal : (choix de la structure de simulation)
15
Demande de la taille de l’ensemble de valeurs : (Pile comme exemple)
Le mode de saisie (mode simulation manuelle) ou génération automatique :
18
CHAPITRE III : Résultats et Discussion
La plus part résultats est présenter dans la partie de conception du programme.
Concernant la fonction time qui calcul le temps d’exécution de tri je ne pouvais pas la
intégrés dans l’application mais j'ai réussi de construire des programme pour faire une
comparaison entre certain algorithme de tri.
Le code C de la fonction time :
La courbe de tri par ABR est la suivant :
19
La courbe de tri par tas est la suivante :
Ces résultats est totalement différents des résultats théorique.
Pour interprétation de cette résultat je vous explique la fonction time qui calcul le temps
d’exécution de tri.
La fonction Time est une fonction de la charge de calcul de votre machine : elle fluctue. Un
programme fonctionnant seul sur une machine peut avoir un temps d’exécution de 10 min
alors que le temps d’exécution passera à 14 min si la machine est utilisée à surfer sur
internet pendant le déroulement des calculs.
Le CPU Time est le temps passé par un programme sur le processeur. Ce temps est une
constante : il ne dépend pas de la charge de travail de votre machine.
Lorsqu’on mesure les performances d’un algorithme de tri on a tendance à mesurer le User
Time alors que cela est une erreur surtout si on travaille sur une station de travail multi-
utilisateurs.
Sous Windows, dès que la machine est sollicitée (ouverture de fichier etc.) à des tâches
annexes (dès qu’on utilise un peu le PC sur lequel le programme tourne) le User Time sera
très différent du CPU Time et ceci dans des proportions importantes : surfer sur internet
pendant les calculs impacte de 6-10% le User Time.
20
Une étude publiée sur le site web http://tablesort.99k.org/comparaison.html montre
la différence entre différents algorithme de tri voici une résumé de cette étude :
Après avoir programmé les 6 méthodes en générant de façon aléatoire des tableaux de
nombres, nous avons mesuré les temps d'exécution pour chaque méthode.
Ces temps d'exécution ne sont pas très précis; ils ont une précision de l'ordre de 40% pour
une mesure d'une seconde; cette précision baisse à 5% quand la mesure depasse 200
secondes. Les temps servent toutefois d'éléments de comparaison, soit entre méthodes de tris,
soit entre tailles différentes.
21
Conclusion
Le bilan est que j’ai présument les objectifs fixés en début de projet. Pour
conclure, on peut dire que ce projet a été particulièrement intéressant.
D’un point de vue pédagogique, le fait de devoir créer une application me a
permis de comprendre encore mieux le fonctionnement des algorithmes de tri et
les structures de données.
En ce qui concerne l’aspect programmation, même s’il ne s’agit pas du but
principal, il s’avère que ce projet me a permis de mettre en application un certain
nombre de connaissances apprises dans des semestres précédentes y compris la
programmation en langage C.
22
Des livres et des ouvrages :
Algorithmes et structures de données génériques
[Michel Divay] Algorithmes et structures de donné
[Rémy Malgouyres – Rita Zrour - Fabien Feschet] INITIATION
L’ALGORITHMIQUE ET À LA PROGRAMMATION
[Caroline Prodhon - Philippe Lacomme - Ren Libo] Comment mesurer les
temps de calcul
Des sites web :
http://www.dailly.info/-030-Algorithmes-de-Tri-
http://fr.openclassrooms.com/
http://www.developpez.com/
http://tablesort.99k.org/comparaison.html
http://fr.wikipedia.org/wiki/Algorithme_de_tri
Bibliographie