+arbresbinaires

publicité
CPGE OUJDA
Les arbres binaires
SPE
Introduction
La structure d'arbre est l'une des plus importantes et des plus spécifiques de
l'informatique.
Exemples d’utilisation :
organisation des fichiers dans les systèmes d'exploitation
internet : DNS (Dynamic Naming System)
mécanismes internes des compilateurs/interpreteurs
Il existe plusieurs types d'arbre : binaires, planaires, ...
Une propriété intrinsèque de la structure d’arbre est la récursivité.
 Un arbre binaire (ou n-aire) est une structure de données de type hiérarchique.
 Les éléments constituant un arbre ont pour nom : racine, nœuds et feuilles.
 Le nœud initial est nommé racine.
 Les éléments terminaux sont des feuilles.
 Dans un arbre binaire, chaque élément possède au plus deux éléments fils au niveau
inférieur.
 Un arbre qui possède deux voire plus de sous éléments est appelé "père", les
éléments inférieurs étant appelés des "fils".
 La hauteur (ou profondeur) d’un noeud est la longueur du chemin qui le lie `a la racine.
Arbres binaires
Un arbre binaire est un arbre tel que les nœuds ont au plus deux fils (gauche et droit).
Les arbres binaires (AB) forment une structure de données qui peut ˆêtre définie
récursivement de la manière suivante : un arbre binaire est
– soit vide,
– soit compos´e d’une racine portant une étiquette (clé) et d’une paire d’arbres binaires,
appelés fils gauche et droit.
Exemple 1:
A
B
D
Arbres binaires de recherche
C
E
F
G
Un arbre binaire de recherche est un arbre binaire qui possède la propriétéfondamentale
suivante:
– tous les nœuds du sous-arbre de gauche d’un nœud de l’arbre ont une valeur inférieure ou
égale `a la sienne.
– tous les nœuds du sous-arbre de droite d’un nœud de l’arbre ont une valeur supérieure ou
égale `a la sienne.
15
10
12
8
2
19
11
22
14
20
25
Parcours d'un arbre binaire :
Le parcours le plus simple à programmer est le parcours dit en profondeur d’abord. Son
principe est simple : pour parcourir un arbre non vide a, on parcourt récursivement
son sous-arbre gauche, puis son sous-arbre droit, la racine de l’arbre pouvant être traitée au
début, entre les deux parcours ou à la fin. Dans le premier cas, on dit que les nœuds sont
traités dans un ordre préfixe, dans le second cas, dans un ordre infixe et dans le troisième
cas, selon un ordre postfixe.
Parcours préfixe, (NGD) :_ tout Nœud est suivi des nœuds de son sous-arbre Gauche puis des
nœuds de son sous-arbre Droit
12
Affichage_prefixe(AB a)
si NON est_vide(a)
Afficher val(a)
Affichage_prefixe(fils_gauche(a))
Affichage_prefixe(fils_droit(a))
1
91
7
67
82
61
12 1 91 67 7 82 61
Parcours infixe, ou symétrique (GND) :_ tout Nœud est précédé des nœuds de
son sous-arbre Gauche et suivi des nœuds de son sous-arbre Droit
Affichage_infixe(AB a)
si NON est_vide(a)
Affichage_infixe(fils_gauche(a))
Afficher val(a)
Affichage_infixe(fils_droit(a))
91 1 67 12 7 61 82
Parcours suffixe, post-fixe (GDN) :_ tout Nœud est précédé des nœuds de son sous-arbre
Gauche et des nœuds de son sous-arbre Droit
Affichage_postfixe(AB a)
si NON est_vide(a)
Affichage_postfixe(fils_gauche(a))
Affichage_postfixe(fils_droit(a))
Afficher val(a)
91 67 1 61 82 7 12
Parcours en largeur.
 Visite les nœuds niveau par niveau depuis la racine:
 Peut-être décrit facilement en utilisant une File.
affichageLargeur(a):
F : File
#File FIFO
Enfiler(a,F)
#enfiler la racine a dans la file F
tantque non vide(F):
n=Défiler(F)
si non vide(n):
Afficher(val(n))
Enfiler(filsGauche(n),F)#enfiler fils gauche de n dans f
Enfiler(filsDroit(n),F) #enfiler fils droit de n dans F
Impl´
ementation en Python par des listes
On impl´emente les arbres binaires non vides par des listes de trois ´el´ements :
[valeur,[fils gauche],[fils droit]]. Ou bien,[[fils gauche], valeur, [fils droit]].
Exemples :
A= [20,[],[]] #A est un arbre qui contient un seul nœud (20)
A= [20, [ 5, [], [] ] , [ 3, [], [] ] ]
A=[20, [ 5, [10,[],[] ], [14,[],[]] ] , [ 3, [], [] ] ]
A=[20, [ 5, [10,[],[] ], [14,[],[]] ] , [ 3, [22,[],[]], [29,[],[]] ] ]
20
EXERCICES
Exercice1
En utilisant la forme ,[[fils gauche], valeur, [fils droit]]. Ecrire en python les
fonctions suivantes ;
1) def inserer(r, x): qui insert un noeud x dans notre arbre binaire de recherche r
2) def prefixer(r):, def infixer(r):, et def postfixer(r): selon les algorithmes précédents
3) def liste_vers_arbre(liste):
"""création d'un arbre à partir d'une liste"""
Exercice2 :
En utilisant la forme [valeur, [fils gauche], [fils droit]]Ecrire les fonctions
suivantes :
1) Fonction qui détermine si un arbre a est vide ou non.
2) Fonction qui retourne la valeur de la racine d’un arbre (étiquette).
3) Fonction qui retourne le fils gauche de l’arbre a .
4) Fonction qui retourne le fils Droit de l’arbre a .
5) Fonction qui fait le Parcourt d’ un arbre en largeur
6) Déterminer si un nœud est une feuille
7) Hauteur d’un arbre
8) Calculer le nombre de nœuds d’un arbre
9) Calculer le nombre de feuilles dans un arbre
10) Fonction de recherche dans un arbre binaire quelconque
Solutions
Exercice1 :
def inserer(r, x):
"""insertion d'un noeud dans notre arbre binaire"""
if r == []:
r.append([])
r.append(x)
r.append([])
elif x < r[1]: inserer(r[0], x)
else: inserer(r[2], x)
def prefixer(r):
"""parcours préfixé"""
if r == []: return None
else:
print r[1],
prefixer(r[0])
prefixer(r[2])
def infixer(r):
"""parcours infixé"""
if r == []: return None
else:
infixer(r[0])
print r[1],
infixer(r[2])
def postfixer(r):
"""parcours postfixé"""
if r == []: return None
else:
postfixer(r[0])
postfixer(r[2])
print r[1],
def liste_vers_arbre(liste):
"""création d'un arbre à partir d'une liste"""
arbre = []
for i in liste: inserer(arbre, i)
return arbre
import random
liste = []
for i in range(50):
liste.append(i)
random.shuffle(liste)
a=liste_vers_arbre(liste)
prefixer(a)
infixer(a)
postfixer(a)
Solutions
Exercice2 :
1: defvide(a):
return a==[]
2: def val(a):
if a!=[]:
return a[0]
else:
return None
3:def filsDroit(a):
ifnot vide(a):
return a[2]
else:
return []
5:
def parcoursLargeur(a):
F=[] #File FIFO
F.append(a) #enfiler la racine a dans la file F
while not vide(F):
n=F[0] ; F=F[1:] #défiler F (récupérer la tête)
print(val(n),end=' ')
if not vide(filsGauche(n))):
F.append(filsGauche(n))
#enfiler le fils gauche de n dans F
if not vide(filsDroit(n))):
F.append(filsDroit(n)) #enfiler le fils droit de n dans F
print()
6:
def estFeuille(a):
if vide(a) : return False
return a[1]==[] and a[2]==[]
7:
def hauteur(a):
if vide(a)or estFeuille(a):
return 0
else:
return 1 + max(hauteur(filsGauche(a)),hauteur(filsDroit(a)))
8:
def nombreNoeuds(a):
if vide(a):
return 0
else:
return 1+ nombreNoeuds(filsGauche(a)) + nombreNoeuds(filsDroit(a))
9:
def nombreFeuilles(a):
if vide(a):
return 0
elif estFeuille(a):
return 1
else:
return nombreFeuilles(filsGauche(a))+ nombreFeuilles(filsDroit(a))
10 :
Def existe(a, x):
if vide(a):
return False
else:
if val(a) ==x:
return True
else:
return existe(filsGauche(a),x) or existe(filsDroit(a), x)
Téléchargement