Sujet 4 :Arbres Binaires de Recherche

publicité
Sujet 4 :Arbres
Binaires de Recherche
INSA 2e année MIC
Algorithmique & Programmation (semestre 4)
3 avril 2015
Les objectifs de ce TP sont les suivants :
comprendre les opérations du type abstrait de données Arbre Binaire de Recherche
poursuivre la compréhension des notions de généricité
comprendre la notion de clé associée à un élément
concevoir et développer un algorithme de recherche
acquérir une méthodologie pour eectuer des tests de performance d'algorithmes et
des comparaisons entre algorithmes
Remarques
créer un nouveau répertoire pour ce sujet de TP,
les noms des chiers ne doivent pas comporter de majuscules,
Ce sujet dure au maximum 2 séances de TP.
Contexte
On souhaite gérer un ensemble d'informations à l'aide d'un Arbre Binaire de Recherche (ABR).
On va créer un paquetage générique d'ABR que l'on testera avec un type d'information spécique. En pratique, l'ABR sera utilisé pour gérer un annuaire similaire à celui considéré au TP
précédent.
Pour représenter un annuaire, on disposera donc d'une liste ordonnée et d'un ABR. Dans les
deux cas, vous allez mettre un point un algorithme de recherche et eectuer des comparaisons
de ces deux algorithmes en termes de performances exprimées sur des mesures à dénir lors du
TP.
1
1
Annuaire représenté par un ABR
On suppose que les éléments de l'ABR seront diérenciés par une
totalement les éléments entre eux.
clé
qui permet d'ordonner
1.1 Création du paquetage générique d'ABR
Ce paquetage, arbre_bin_recherche_cle_g, vous est partiellement fourni. Il exporte :
un type Un_ABR limité privé
trois exceptions : Element_Deja_Present, Element_Non_Present et Arbre_Vide.
les primitives :
Liberer(A) : libérer la mémoire utilisée pour A.
Est_Vide(A) : renvoie vrai si A est vide.
Taille(A) : retourne le nombre d'éléments de A.
Racine(A) : retourne l'objet de type Element présent à la racine de l'arbre. Une exception est levée si l'arbre est vide.
Appartient(C, A) : retourne vrai si l'élément ce cle C est présent dans A.
Arbre_to_string(A) : retourne la chaine de caractères composée des éléments de A dans
l'ordre en eectuant un parcours inxe d'un arbre (dit parcours GRD).
Inserer(E, A) : insérer l'élément E dans l'ABR A en respectant la relation d'ordre. Une
exception est levée si l'élément est déjà présent ; A doit rester ordonnée après l'insertion
de E.
Supprimer(E, A) : supprime l'élément E de l'ABR A. Une exception est levée si l'élément n'est pas présent dans A. Remarque : on pourrait aussi dénir une opération de
suppression à partir de la valeur d'une clé.
Travail à réaliser
Identier tous les paramètres de généricité du paquetage (types et sous-programmes). N'oubliez pas qu'une clé doit être associée à chaque élément et que la relation d'ordre se base
sur les valeurs des clés. Faire valider par un enseignant et compléter la spécication du
paquetage générique.
Développer le corps du paquetage progressivement, en y intégrant un par un les sousprogrammes manquant. Exécuter les tests de chaque sous-programme progressivement (voir
le point suivant).
Récupérer le programme tester_abr_entier.adb. Ce programme teste les sous-programmes
dans le cas d'un ABR contenant des entiers. Ecrire l'instanciation correspondante et lancer
les tests au fur et à mesure de vos développements (commenter les tests associés à des
sous-programmes non terminés).
1.2 Instanciation : ABR de contacts
Récupérer les paquetages contact_cle et pointeurs_de_strings.ads ainsi que les chiers
afficher_test.ads et afficher_test.adb. Attention, le paquetage contact_cle a été modié
par rapport au paquetage contact du TP précédent et explicite maintenant une clé.
Travail à réaliser
Créer un programme de test appelé tester_abr_contacts, permettant :
d'instancier le paquetage générique d'arbre pour le type Un_Contact ;
de lire un annuaire à partir d'un chier texte et de créer l'ABR correspondant (reprendre
la procédure de lecture écrite lors du TP précédent ou consulter l'annexe 6.1) ;
d'acher l'ABR créé.
2
Donner le graphe de dépendance des diérentes unités utilisées (faire valider par un enseignant).
2
Annuaire représenté par une liste ordonnée
Récupérer le paquetage générique liste_ordonnee_cle_g. Il sera utilisé dans la section suivante.
3
Algorithmes de Recherche
3.1 Principes généraux
Lors du TP précédent, vous avez développé un algorithme de ltrage sur une liste ordonnée. On
parle de ltrage d'un ensemble d'éléments lorsqu'on souhaite récupérer les informations associées
à plusieurs éléments vériant tous une même condition de ltrage. Par exemple, on veut pouvoir
connaitre tous les contacts ayant une spécialité donnée ou exerçant dans une même ville. Dans
le cas général, plusieurs objets de type Element peuvent donc respecter la condition de ltrage.
Dans ce TP, on va s'intéresser seulement au développement d'un algorithme de recherche. La
recherche d'un élément dans un ensemble permet de récupérer toutes les informations associées
à l'élément donné. Par exemple, on cherche toutes les informations (nom, prénom, ville, spécialité, téléphone) sur une personne donnée à partir de son nom (en supposant que chaque personne
n'est présente qu'en un seul exemplaire dans l'ensemble et si ce n'est pas le cas en retournant la
première occurrence trouvée). Ainsi, le résultat d'une recherche est un unique élément.
Un algorithme de recherche (ou de ltrage) peut s'appliquer que les objets soient stockés dans une
liste ordonnée ou dans un ABR (ou d'autres structures de données). Pour un même ensemble de
contacts, stockés dans une liste ordonnée ou dans un ABR (ou autre), la recherche (ou le ltrage)
doit fournir le même résultat.
L'ecacité d'un algorithme de recherche est liée à l'utilisation d'une clé pour chaque élément en
garantissant l'unicité. En eet, dans ce cas, les recherches peuvent être stoppées dès que l'on est
certain que la liste ordonnée ou l'ABR ne contient plus d'éléments pouvant avoir la valeur de clé
recherchée.
Vous allez développer deux algorithmes de recherche : le premier s'appliquera sur les listes ordonnées et le second sur les ABR. Il vous sera ensuite demander d'évaluer les performances de
ces algorithmes an de les comparer.
Travail à réaliser
Répondre aux questions ci-dessous et faire valider les réponses par un enseignant (ou vérier
dans le cours).
quelle est la complexité au pire d'un algorithme de recherche d'un élément à partir de sa
clé dans un ABR (ordonné par les clés) équilibré ?
quelle est la complexité au pire lorsque l'ABR n'est pas équilibré ?
quelle est la complexité au pire d'un algorithme de recherche d'un élément à partir de sa
clé dans une liste ordonnée par les clés ?
quelle est la complexité au pire d'un algorithme de recherche d'un élément à partir d'un
champ autre que sa clé dans un ABR (ordonné par les clés) équilibré ?
quelle est la complexité au pire d'un algorithme de recherche d'un élément à partir d'un
champ autre que sa clé dans une liste ordonnée par les clés ?
3
3.2 Recherche sur un ABR
On souhaite développer un annuaire inversé permettant d'obtenir toutes les informations
sur un contact à partir de son numéro de téléphone.
On note que pour les annuaires considérés, la clé ne peut être que le numéro de téléphone (les
noms, prénoms, villes ou spécialités ne sont pas des clés pour les contacts). L'utilisation d'un
ABR ordonné par numéro de téléphone pour réaliser un annuaire inversé est donc pertinente.
Travail à réaliser
Modier le paquetage générique arbre_bin_recherche_cle_g pour y ajouter une fonction
de recherche.
Créer un programme de test appelé gerer_annuaire_inverse permettant de lire un chier
d'annuaire et de créer un ABR ordonné par numéro de téléphone (clé).
Vérier, dans ce programme de test, le fonctionnement de la procédure de recherche en
générant et en achant le résultat de plusieurs recherches (recherche du premier élément,
d'une feuille de l'arbre, ou d'un élément d'un noeud interne).
3.3 Recherche sur une liste ordonnée
Le développement d'un algorithme de recherche dans une liste ordonnée est similaire.
Travail à réaliser
Modier le paquetage générique liste_ordonnee_cle_g pour y ajouter une fonction de
recherche.
Vérier, dans le programme de test, gerer_annuaire_inverse, le fonctionnement de la
procédure de recherche sur des listes ordonnées par numéro de téléphone. Pour cela, à la
lecture du chier annuaire, il faut mémoriser les contacts à la fois dans un ABR et dans
une liste ordonnée.
4
Tests de performance
Nous nous étions limités, jusqu'à ce TP, à vous demander de vérier que les algorithmes développés étaient corrects à partir d'un ensemble de tests que l'on devait dénir.
Cependant, les tests de validité (ou de correction) ne susent pas dans de très nombreuses situations.
Il est également important de montrer que vos algorithmes sont ecaces en théorie (en donnant
leur complexité, cela sera vu en détail en 3MIC) et en pratique. Pour les TPs de 2MIC, nous
nous contenterons de mesurer leur ecacité en pratique. On parle alors de tests de performance.
4.1 Méthodologie pour les tests de performance
Avant de tester l'ecacité d'un algorithme, il convient tout d'abord de dénir les paramètres que
l'on souhaite mesurer et qui paraissent représentatifs de son ecacité.
Il est ensuite nécessaire de sélectionner (ou de créer) des jeux de données représentatifs.
Enn, il faut recueillir les valeurs des paramètres à mesurer pour chacun des jeux de données et
analyser les valeurs obtenues. Pour cela, on peut développer un programme appelant l'algorithme
dont on veut évaluer les performances sur chacun des jeux de données ou le faire "à la main".
Il est impératif de bien comprendre la distinction entre tests de validité (de correction) et tests de performance (ou d'ecacité). Si ces notions vous paraissent oues,
demandez des éclaircissements à vos encadrants.
4
Travail à réaliser
Les paramètre de mesure que nous allons utiliser sont le nombre de comparaison entre 2
éléments et le temps de calcul an d'évaluer les performances d'un algorithme de recherche
utilisant une liste ordonnée ou un ABR ;
Rechercher comment mesurer les temps de calcul en ADA (si vous ne trouvez pas, limitez
vous au nombre de comparaison entre 2 élements) ;
Utiliser les chiers d'annuaire proposés ;
Eectuer les comparaisons et construire des tableaux avec les valeurs des paramètres.
4.2 Comparaison de vos algorithmes
Comparer l'ecacité respective de vos algorithmes (recherche dans une liste ordonnée versus
recherche dans un ABR) sur des jeux de données identiques et pour un même ensemble de
paramètres de mesure. Que pouvez-vous en conclure ?
On s'attend à ce que la recherche sur un ABR soit plus ecace à la recherche sur une liste
ordonnée. Votre conclusion est-elle cohérente par rapport à ce qui était attendu ? Est-ce vérié
pour tous les chiers d'annuaire ? Justier votre réponse et faire valider par un enseignant.
5
Pour aller plus loin
Reprendre la démarche de ce TP dans le cas d'un algorithme de ltrage.
La principale diculté réside dans la construction (ecace) de l'ensemble des résultats d'un
ltrage pour un ABR.
5
6
Annexes
6.1 Lecture de données dans un chier texte
Pour
lire des données dans un chier texte :
ouvrir un chier (open) en mode lecture (in_file).
le parcourir ligne par ligne (get_line) jusqu'à la n (end_of_file).
fermer le chier (close).
Pour gérer les chiers, le langage Ada propose un type prédéni appelé file_type. En supposant
que le chier que l'on souhaite lire s'appelle data.txt, le principe général de lecture est fourni
dans le listing ci-dessous.
1
2
3
4
5
6
7
8
9
10
11
12
13
F : File_Type ;
Lig ne : s t r i n g ( 1 . . 8 0 ) ;
Last : N a t u r a l ;
C : Un_Contact ;
begin −− l e c t u r e
Open (F , In_File , " data . t x t " ) ;
while not End_Of_File (F) loop
Get_Line (F , Ligne , Last ) ;
C := C o n v e r t i r ( Lig ne ( 1 . . Last ) ) ;
........
end loop ;
C l o s e (F) ;
end ; −− l e c t u r e
Listing 1 Lecture des lignes d'un chier
Remarque : pour la conversion d'une ligne lue en un contact, vous pouvez reprendre le sousprogramme lire_mot réalisé au premier semestre et rappelé ci-dessous.
1
procedure Lire_Mot ( S : S t r i n g ; Deb , Fin : out I n t e g e r ) i s
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
begin
−− c h e r c h e l e debut e t l a f i n du p r e m i e r token
−− s i aucun token n ' e s t t r o u v e on impose en s o r t i e que Deb > Fin
Deb := S ' F i r s t ;
Fin := Deb − 1;
while Deb <= S ' l a s t and then S ( Deb ) = ' ' loop
Deb := Deb+1;
−− r e c h e r c h e du debut du 1 e r mot
end loop ;
i f Deb <= S ' Last then
Fin := Deb ;
while Fin <= S ' Last and then S ( Fin ) /= ' ' loop
Fin := Fin +1;
−− r e c h e r c h e de l a f i n du 1 e r mot
end loop ;
Fin := Fin − 1;
end i f ;
end Lire_Mot ;
Listing 2 Lire un mot dans une chaine
La procédure de conversion doit eectuer autant d'appels que nécessaire à la procédure lire_mot
et retourner un élément de type Un_Contact ou une exception si une erreur de lecture survient.
6
Téléchargement