====== Exercice : Arbre binaire de recherche ======
Il s'agit de l'exercice 3 de ce {{ .:spe-numerique-informatique-2021-metro-cand-libre-2-sujet-officiel.pdf |sujet}}
//Cet exercice porte sur les arbres binaires de recherche et la programmation orientée objet.//
On rappelle qu'un arbre binaire est composé de nœuds, chacun des nœuds possédant éventuellement un sous-arbre gauche et éventuellement un sous-arbre droit. Un nœud sans sous-arbre est appelé feuille. La taille d'un arbre est le nombre de nœuds qu’il contient ; sa hauteur est le nombre de nœuds du plus long chemin qui joint le nœud racine à l’une des feuilles. Ainsi la hauteur d’un arbre réduit à un nœud, c’est-à-dire la racine, est 1.
Dans un arbre binaire de recherche, chaque nœud contient une clé, ici un nombre entier, qui est :
* strictement supérieure à toutes les clés des nœuds du sous-arbre gauche ;
* strictement inférieure à toutes les clés des nœuds du sous-arbre droit.
Ainsi les clés de cet arbre sont toutes distinctes.
Un arbre binaire de recherche est dit « bien construit » s’il n'existe pas d'arbre de hauteur
inférieure qui pourrait contenir tous ses nœuds.
On considère l’arbre binaire de recherche ci-dessous.
{{ .:arbre_binaire_recherche.png?direct&600 |}}
=== Question 1 ===
- Quelle est la taille de l'arbre ci-dessus ?
- Quelle est sa hauteur ?
=== Question 2 ===
Cet arbre binaire de recherche n'est pas « bien construit ».
Proposer un arbre binaire de recherche contenant les mêmes clés et dont la hauteur est plus petite que celle de l’arbre initial.
=== Question 3 ===
Les classes ''Noeud'' et ''Arbre'' ci-dessous permettent de mettre en œuvre en Python la structure d'arbre binaire de recherche. La méthode ''insere'' permet d’insérer récursivement une nouvelle clé.
class Noeud:
def __init__(self, cle):
self.cle = cle
self.gauche = None
self.droit = None
def insere(self, cle):
if cle < self.cle :
if self.gauche == None :
self.gauche = Noeud(cle)
else :
self.gauche.insere(cle)
elif cle > self.cle :
if self.droit == None :
self.droit = Noeud(cle)
else :
self.droit.insere(cle)
class Arbre:
def __init__(self, cle):
self.racine = Noeud(cle)
def insere(self, cle):
self.racine.insere(cle)
Donner la représentation de l’arbre codé par les instructions ci-dessous.
a = Arbre(10)
a.insere(20)
a.insere(15)
a.insere(12)
a.insere(8)
a.insere(4)
a.insere(5)
=== Question 4 ===
Pour calculer la hauteur d'un arbre non vide, on a écrit la méthode ci-dessous dans la classe ''Noeud''.
N'hésitez pas à améliorer cette fonction : cet enchaînement de tests n'est pas terrible :-|
def hauteur(self):
if self.gauche == None and self.droit == None:
return 1
if self.gauche == None:
return 1 + self.droit.hauteur()
elif self.droit == None:
return 1 + self.gauche.hauteur()
else:
hg = self.gauche.hauteur()
hd = self.droit.hauteur()
if hg > hd:
return hg+1
else:
return hd+1
Écrire la méthode hauteur de la classe Arbre qui renvoie la hauteur de l'arbre.
=== Question 5 ===
Écrire les méthodes taille des classes ''Noeud'' et ''Arbre'' permettant de calculer la taille d’un arbre.
=== Question 6 ===
On souhaite écrire une méthode ''bien_construit'' de la classe ''Arbre'' qui renvoie la valeur ''True'' si l'arbre est « bien construit » et ''False'' sinon.
On rappelle que la taille maximale d'un arbre binaire de recherche de hauteur $h$ est $2^h-1$.
- Quelle est la taille minimale, notée $t_{min}$, d'un arbre binaire de recherche « bien construit » de hauteur $h$ ?
- Écrire la méthode ''bien_construit'' demandée.