• Aucun résultat trouvé

Programmation objet

N/A
N/A
Protected

Academic year: 2022

Partager "Programmation objet"

Copied!
18
0
0

Texte intégral

(1)

Département Informatique Département Informatique

Structures de données – partie 4 Arbres non binaires

Arbre lexical

Tables de hachage

Programmation objet

Cours n°9

(2)

Département Informatique

Département Informatique Arbres non binaires

Nous avons vu l'importance des structures de type arbre binaire pour la recherche d'éléments par la valeur.

Cette structure n'est possible que si la recherche peut utiliser un critère de séparation binaire.

Le temps de parcours est très faible (logarithmique)

La structure n'est néanmons pas adaptée à tous les cas (critère de sélection non binaire, grand nombre de valeurs identiques à stocker, arbre très déséquilibré)

Dans certains cas l'utilisation d'un arbre n-aire (avec n>2) est préférable.

(3)

Département Informatique

Département Informatique Principe

A chaque feuille de l'arbre correspond au plus n feuilles « enfants ».

Il faut donc un critère permettant de choisir, le plus rapidement possible, la « branche » fille à explorer.

On peut voir les implémentations possibles de deux manières : Une feuille possède plusieurs enfants (par exemple une liste chaînée, un tableau, etc...)

Une feuille possède un enfant et une soeur Les performances sont similaires dans les deux cas.

Si le nombre de soeurs est trop important, le temps de parcours est trop long, sauf si on utilise une structure de type... arbre de recherche !

(4)

Département Informatique

Département Informatique Exemple d'arbre non binaire : un arbre lexical

Nous allons stocker des mots dans un arbre.

Les mots sont composés de lettres, donc 26 valeurs possibles si l'on ne distingue pas la casse et qu'on n'utilise pas les accents.

Afin d'avoir une recherche rapide sur un mot, un arbre de type lexical est très intéressant.

Dans ce type d'arbre, les feuilles contiennent des caractères Un rang dans l'arbre correspond à une position dans le mot.

(5)

Département Informatique

Département Informatique Exemple

L'arbre lexical suivant contient les mots :

Arbre, art,des, dessin.

A

R B

T*

R E*

D E S*

S I

N*

La recherche peut aller très vite :

Bois n'est pas dans l'arbre (1 itération)

Desert n'est pas dans l'arbre (4 itérations)

Dessin est dans l'arbre (6 itérations)

Le nombre maximal d'itérations est égal à la profondeur de l'arbre, donc au nombre de lettres Ex : en

français 25

On indique par un booléen que la feuille est « finale »

(6)

Département Informatique

Département Informatique Exemple d'implémentation en C++

Pour chaque feuille ou noeud de l'arbre, les informations nécessaires :

• La lettre à stocker (char)

• Indication de fin de mot (bool)

• Feuilles suivantes (filles, au plus 26)

Il y a plusieurs méthodes pour lier les feuilles suivantes :

• Tableau de 26 cases (NULL par défaut)

• Liste chaînée de feuilles soeurs

• Arbre de recherche suivant la valeur Facile à programmer Très rapide à chercher Espace mémoire moyen Aucune n'est préférable, le contexte

décidera de la plus adaptée.

Simple à programmer Rapide à chercher (indice) Espace mémoire important

Programmation délicate Long à chercher (parcours)

Espace mémoire restreint

(7)

Département Informatique

Département Informatique Trois implémentations possibles

struct feuille {

char lettre;

bool final;

pfeuille filles[26];

};

struct feuille {

char lettre;

bool final;

pfeuille fille_suivante;

pfeuille soeur_suivante;

};

struct feuille {

bool final;

std::map<char, pfeuille>

filles;

};

typedef feuille* pfeuille;

(8)

Département Informatique Département Informatique

On a bien évidemment tout intérêt à utiliser des pointeurs intelligents pour l'arbre afin de supprimer les risques de fuite mémoire (ou pire, de double libération) : néanmoins ceci ajoute de l'espace mémoire (1 pointeur intelligent = 2 « vrais »

pointeurs + 1 entier, soit 96 bits au lieu de 32)

Une feuille prend environ 64 bits pour une seule lettre.

Nous allons choisir pour détailler la solution du tableau de feuilles,

en utilisant un std::vector< iut::shared_ptr< feuille > >

Bien sûr, un feuille[26] ferait l'affaire, mais avec du code en plus pour

(9)

Département Informatique

Département Informatique Implémentation C++

class arbre_lexical {

typedef shared_ptr<feuille> pfeuille;

struct feuille {

char lettre;

bool final;

std::vector<pfeuille> filles;

feuille(char l, bool f = false):

lettre(l),final(f), filles(26){}

static int indice(char c){return c-'A');}

};

pfeuille racine;

public:

void ajoute(const std::string& mot);

bool cherche(const std::string& mot) const;

};

(10)

Département Informatique

Département Informatique Ajout d'un mot dans l'arbre

• Parcours du mot lettre à lettre (itération ou récursivité)

• Passage de chaque lettre en majuscule (perte de la casse)

• Filtrage des eventuels « mauvais » caractères (exceptions)

• Si la lettre n'est pas présente dans l'arbre au rang voulu, la rajouter

• Si la lettre est la dernière du mot, placer le booléen à vrai

• Si la lettre n'est pas la dernière, recommancer au rang suivant

Comme souvent dans les arbres, l'algorithme le plus simple sera récursif.

On remarque que la notion de rang est ici importante : le paramètre sera nécessaire à la fonction récursive.

Une fonction d'ajout pour la feuille sera donc utile.

De même, on transmettra le mot en entier à la feuille.

(11)

Département Informatique Département Informatique

void arbre_lexical::ajoute(const std::string& mot) { racine->ajoute(mot,0);

} Une racine doit être présente

On commence par le rang 0 (première lettre)

arbre_lexical::arbre_lexical()

:racine(new feuille(0,false)) {}

Racine systématique

arbre_lexical::feuille::feuille(char l, bool f = false)

:lettre(l),final(f), filles(26){} 26 lettres

(12)

Département Informatique Département Informatique

void arbre_lexical::feuille::ajoute(const std::string& mot, int rang)

{

char L = Lettre(mot,rang);

if(!EstCorrecte(L))

throw erreur_arbre("Mauvais caractere");

bool is_final = EstFinal(mot,rang);

int i = indice(L); // passage en indice if(filles[i]==NULL)

filles[i] = new feuille(L,is_final);

if(!is_final)

filles[i]->ajoute(mot,rang+1);

Passage en indice à partir du caractère

On continue au rang suivant

(13)

Département Informatique

Département Informatique Recherche dans l'arbre

• Parcourir lettre à lettre le mot à chercher

• Normaliser la lettre (perte de la casse, etc...)

• Si la lettre n'est pas présente au rang indiqué, c'est raté

• Si la lettre est la dernière du mot, voir si la feuille est "finale"

• Si tout ok, continuer au rang suivant (récursivité ou itération)

Nous allons procéder comme pour l'ajout...

(14)

Département Informatique Département Informatique

bool arbre_lexical::cherche (const std::string& mot) const {

return racine->cherche(mot,0);

}

La recherche ne modifie pas l'objet

On cherche à partir de la racine pour le rang 0

(première lettre)

(15)

Département Informatique Département Informatique

bool arbre_lexical::feuille::cherche

(const std::string& mot, int rang) const {

bool retour = false,

is_final = (rang>0)?EstFinal(mot, rang-1):false; int i = indice(Lettre(mot,rang));

if(is_final)

retour = final;

else if(filles[i]!=NULL) retour =

filles[i]->cherche(mot, rang+1);

return retour;

}

Décalage dû à la première feuille de

l'arbre

On continue au rang suivant

(16)

Département Informatique Département Informatique

Avec une telle structure de données, l'utilisation d'un dictionnaire complet est aisée : la recherche est très rapide. Cette structure permet même

assez facilement d'implémenter des fonctionnalités de complétion automatique du mot...

Test avec un dictionnaire complet de 75000 mots :

16 ms de temps CPU avec un std::vector<std::string>

<1ms de temps CPU avec un arbre lexical

30 MO occupés par l'arbre lexical (avec cette impl.) 4 MO occupés par le tableau

(17)

Département Informatique

Département Informatique Tables de hachage

On remarque que l'arbre précédent est rapide parce qu'on retrouve directement l'indice à partir de la valeur à stocker.

Une telle méthode s'appelle du hachage.

Une fonction de hachage est une fonction associant pour une valeur, un entier donné (toujours le même !) avec si possible une seule valeur entière pour une valeur.

Une table de hachage est une structure de données de type tableau où les éléments sont rangés (indéxés) en fonction de leur contenu, grâce à la fonction de hachage.

La structure peut être extrêmement rapide avec une bonne fonction de hachage.

(18)

Département Informatique Département Informatique

Prochain cours : L'héritage

principes

modes d'héritage syntaxe en C++

A la semaine prochaine !

Références

Documents relatifs

Autant vous le dire tout de suite, pour programmer, il ne faut pas avoir fait vingt ans d'études, ni être le plus grand savant de la planète?. Non, on peut apprendre à programmer

Le robot doit réaliser un carré dont les côtés mesurent 15 cm et changer de couleur à chaque changement de côté (vert, rouge, bleu et violet).

Le plus rapide, le plus facile et sans risque moyen de gagner 1500 eth tous les jours 100... 247

vos patients passent moins de temps au fauteuil, tandis que vous pouvez recueillir facilement toutes les données essentielles dont vous avez besoin pour créer une empreinte en

L’insertion et la suppression utilisent la rotation ` a gauche et ` a droite d’un arbre lorsqu’il est trop d´ es´ equilibr´ e :.

Complexit´ e des op´ erations pr´ ec´ edentes Pour un arbre binaire de taille n,. la complexit´ e dans le pire des

L’insertion et la suppression utilisent la rotation ` a gauche et ` a droite d’un arbre lorsqu’il est trop d´ es´ equilibr´ e :.

Soit f une fonction continue et périodique sur R à valeurs dans R, admettant une limite réelle quand x tend vers +∞. Montrer que f