arbre binaire
Download
Report
Transcript arbre binaire
Arbres binaires et tables de
hachage
Introduction
Les arborescences sont utilisées :
Dans la vie de tous les jours : pour représenter
des hiérarchies, des classifications, des partitions
Dans le domaine de l'informatique : pour
représenter les informations ci-dessus, et
aussi :
L'organisation interne des fichiers en mémoire
Les mode de calcul d'une expression
L'organisation de données triées
Introduction
Exemple
Introduction
Utilisations
Système de fichier
Parsing de texte (compilation, XML, …)
Base de données (indexation)
Intelligence artificielle (arbres de décision)
Définition
Un arbre est une collection (finie) de noeuds
de même type
Un arbre est défini (récursivement) par :
un premier noeud (racine de l’arbre)
0, 1, 2 ou plusieurs sous-arbres (appelés
descendants de la racine)
Vocabulaire
Définition
L’arité d’un nœud est le nombre de fils de ce
nœud
Binaire: 2 fils
Ternaire: 3 fils
N-aire …
Un arbre binaire est un arbre dans lequel
chaque noeud possède 0, 1 ou 2 fils
Chaque noeud a un descendant gauche et un
descendant droit (éventuellement vides)
Définition
Les arbres binaires
1 élément = 3 parties (agrégat)
Le champ donnée
Le fils gauche (sous-arbre)
Le fils droit (sous-arbre)
Donnée
Gauche
Droite
Les arbres binaires
Déclaration de la structure d’un arbre binaire
typedef struct s_btree {
void
*donnee;
struct s_btree *gauche;
struct s_btree *droite;
} t_btree;
Les opérations de base
Création d’un nouvel arbre
t_btree*btree_new_root(void *donnee, t_btree *gauche,
t_btree *droite)
{
t_btree
*nouvel_arbre;
nouvel_arbre = malloc(sizeof (t_btree));
nouvel_arbre->droite = droite;
nouvel_arbre->gauche = gauche;
nouvel_arbre->donnee = donnee;
return (nouvel_arbre);
}
Les opérations de base
Les parcours en profondeur
Les opérations de base
Affichage ordre Préfixe
void btree_prefixe(t_btree *arbre, void (*f)(void *))
{
if (arbre == NULL)
return ;
else
{
f(arbre->donne);
btree_apply(arbre->gauche, f);
btree_apply(arbre->droite, f);
}
}
Les opérations de base
Affichage ordre Infixe (symétrique)
void btree_infixe(t_btree *arbre, void (*f)(void *))
{
if (arbre == NULL)
return ;
else
{
btree_apply(arbre->gauche, f);
f(arbre->donne);
btree_apply(arbre->droite, f);
}
}
Les opérations de base
Affichage ordre suffixe (postfixe)
void btree_suffixe(t_btree *arbre, void (*f)(void *))
{
if (arbre == NULL)
return ;
else
{
btree_apply(arbre->gauche, f);
btree_apply(arbre->droite, f);
f(arbre->donne);
}
}
Les opérations de base
Parcours en largeur (hiérarchique)
Exercice
Exercice
Parcours préfixe:
ABCEIFJDGHKL
Parcours Infixe:
E I C F J B G D K H LA
Parcours suffixe:
IEJFCGKLHDBA
Parcours en largeur:
ABCDEFGHIJKL
Les arbres binaires de recherche (ABR)
Un arbre binaire de recherche est un arbre
binaire dans lequel la valeur de chaque
sommet est
supérieure [ou égale] à toutes les valeurs
étiquetant les sommets du sous-arbre gauche de
ce sommet,
et inférieure à toutes les valeurs étiquetant les
sommets du sous-arbre droit de ce sommet.
Les arbres binaires de recherche (ABR)
Algorithme de construction
Soit val la valeur à placer dans l’ABR (l’ajout se fera
toujours sur une «feuille» : arbre binaire dont le Fils G et
le Fils D sont vides)
Si l’arbre est vide, en créer un, réduit à sa racine, étiquetée avec
val
Sinon si val ≤ valeur portée par la racine, alors l’ajouter au sousarbre gauche : si cet arbre n’est pas vide, reprendre l’algorithme
sur ce sous-arbre
Sinon l’ajouter au sous-arbre droit : si cet arbre n’est pas vide,
reprendre l’algorithme sur ce sous-arbre
Avantages des ABR
Faible complexité pour la recherche
O(n) pour trouver une valeur où n représente
la profondeur de l’arbre
Tables de hachages
Définition
Ensemble de données de la forme (k, v)
L’objectif est de retrouver v en fournissant k:
K est appelé la clé
V est une valeur associée à k
On peut voir une table T comme une fonction d’un ensemble de
clés k vers un ensemble de valeur v
Exemple:
K = ensemble des départements
V = ensemble des préfectures
La fonction de hachage
Les collisions
L’inconvénient de cette idée est que deux clés peuvent
être hachées dans la même case de la table : collision.
Exemple : si les clés sont des valeurs numériques, on
peut considérer la fonction de hachage simple suivante :
H(k) = k mod m
Pour m = 10000 on a :
H(4325678) = h(35678) = 5678
Résolution des collisions
Choix de la fonction de hachage
L’hypothèse «hachage uniforme simple» est
difficile à garantir, mais il existe des
techniques qui fonctionnent bien en pratique.
Une bonne fonction de hachage doit
distribuer les clés uniformément dans les
cases de la table.
La fonction modulo
On suppose que toutes les clés sont des
entiers naturels.
A chaque clé k, on associe une case en
prenant le reste de la division de k par m
H(k) = k mod m
Cette méthode est simple, mais peut donner
de mauvaises répartitions si m est mal choisi.
La fonction modulo
On choisit m premier assez éloigné des puissances de 2 et des
puissances de 10
Exemple : On veut une table de hachage pour conserver environs n =
2000 chaînes de caractères.
L’examen de 3 éléments en moyenne en cas de recherche infructueuse
n’est pas catastrophique
On alloue une table de taille m = 701
701 est premier
701 est proche de 2000/3
701 n’est pas proche d’une puissance de 2
(512 = 29 < 701 < 210 = 1024)
La fonction modulo
Pour des chaînes de caractères, on applique
le même principe en prenant pour k le
nombre formé en concaténant les caractères.
En additionnant les codes ascii des caractères
En représentant chaque caractère en base 256
Conclusion
Les tables de hachage ont de gros avantages
…
… mais aussi des inconvénients, si le
nombre de données est important la fonction
de hachage devient critique.