Arbres - Exercices - 2
Auteur : Gilles Lassus
Exercice 1
Exercice 2 du sujet 2022 Nouvelle-Caledonie J2
Correction 1.
C'est un arbre binaire car chaque nĆud possĂšde au maximum deux fils.
Correction 2.a
V
est un dictionnaire.
Correction 2.b
V['J']
Correction 2.c
đ Script Python | |
---|---|
1 2 3 4 5 |
|
Correction 2.d
đ Script Python | |
---|---|
1 2 3 4 5 6 7 |
|
Correction 3.
Cet algorithme calcule le nombre total de nĆuds de l'arbre, donc la taille de l'arbre. C'est un algorithme rĂ©cursif qui va renvoyer, si on n'est pas positionnĂ© sur un arbre vide, la valeur 1 (correspond au nĆud racine sur lequel on est positionnĂ©), plus la taille des deux sous-arbres gauche et droits.
Correction 4.a
Le parcours est A-B-C-E-D-F-G-I-H-J
Correction 4.b
C'est un parcours préfixe.
Exercice 2
2020, sujet 0
Question 1
DĂ©terminer la taille et la hauteur de lâarbre binaire suivant :
Question 2
On dĂ©cide de numĂ©roter en binaire les nĆuds dâun arbre binaire de la façon suivante :
- la racine correspond Ă 1 ;
- la numĂ©rotation pour un fils gauche sâobtient en ajoutant le chiffre 0 Ă droite au numĂ©ro de son pĂšre ;
- la numĂ©rotation pour un fils droit sâobtient en ajoutant le chiffre 1 Ă droite au numĂ©ro de son pĂšre ;
Par exemple, dans lâarbre ci-dessous, on a utilisĂ© ce procĂ©dĂ© pour numĂ©roter les nĆuds A, B, C, E et F .
- Dans lâexemple prĂ©cĂ©dent, quel est le numĂ©ro en binaire associĂ© au nĆud G ?
- Quel est le nĆud dont le numĂ©ro en binaire vaut 13 en dĂ©cimal ?
- En notant \(h\) la hauteur de lâarbre, sur combien de bits seront numĂ©rotĂ©s les nĆuds les plus en bas ?
- Justifier que pour tout arbre de hauteur \(h\) et de taille \(n \geqslant 2\), on a : \(h\leqslant n \leqslant 2^h-1\)
Question 3
Un arbre binaire est dit complet si tous les niveaux de lâarbre sont remplis.
On dĂ©cide de reprĂ©senter un arbre binaire complet par un tableau de taille n + 1, oĂč n est la taille de lâarbre, de la façon suivante :
- La racine a pour indice 1 ;
- Le fils gauche du nĆud dâindice i a pour indice \(2 \times i\) ;
- Le fils droit du nĆud dâindice i a pour indice \(2 \times i + 1\) ;
- On place la taille \(n\) de lâarbre dans la case dâindice 0.
RĂ©pondre aux questions suivantes :
- DĂ©terminer le tableau qui reprĂ©sente lâarbre binaire complet de lâexemple prĂ©cĂ©dent.
- On considĂšre le pĂšre du nĆud dâindice \(i\) avec \(i \geqslant 2\). Quel est son indice dans le tableau ?
Question 4
On se place dans le cas particulier dâun arbre binaire de recherche complet oĂč les nĆuds contiennent des entiers et pour lequel la valeur de chaque noeud est supĂ©rieure Ă celles des noeuds de son fils gauche, et infĂ©rieure Ă celles des noeuds de son fils droit.
Ăcrire une fonction recherche
ayant pour paramĂštres un arbre arbre
et un élément element
. Cette
fonction renvoie True
si element
est dans lâarbre et False
sinon. Lâarbre sera reprĂ©sentĂ© par un tableau
comme dans la question précédente.
corrigé
Q1 La taille est 9, la hauteur est 4.
Q2 1. G est associé à 1010.
Q2 2. 13 s'Ă©crit 1101 en binaire, c'est donc le nĆud I.
Q2 3. Les nĆuds les plus en bas sont notĂ©s sur \(h\) bits.
Q2 4. L'arbre de hauteur \(h\) de taille minimale est l'arbre filiforme, qui est de taille \(h\).
L'arbre de hauteur \(h\) de taille maximale est l'arbre complet, qui est de taille \(2^h-1\). Si \(n\) est la taille d'un arbre quelconque de taille \(h\), on a donc bien
\(h \leqslant n \leqslant 2^h-1\).
Q3 1. Tableau : [15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O]
.
Q3 2. Le pĂšre du nĆud d'indice i
a pour indice i//2
.
Q4 :
def recherche(arbre, element):
i = 1
while i < len(arbre):
if arbre[i] == element:
return True
if element < arbre[i]:
i = 2*i # on se place sur le fils gauche
else:
i = 2*i + 1 # on se place sur le fils droit
return False
Exercice 3
2021, MĂ©tropole sujet 1
Dans cet exercice, les arbres binaires de recherche ne peuvent pas comporter plusieurs fois la
mĂȘme clĂ©. De plus, un arbre binaire de recherche limitĂ© Ă un nĆud a une hauteur de 1.
On considĂšre lâarbre binaire de recherche reprĂ©sentĂ© ci-dessous (figure 1), oĂč val
représente un entier :
1.a Donner le nombre de feuilles de cet arbre et préciser leur valeur (étiquette).
1.b Donner le sous arbre-gauche du nĆud 23.
1.c Donner la hauteur et la taille de lâarbre.
1.d Donner les valeurs entiĂšres possibles de val
pour cet arbre binaire de recherche.
On suppose, pour la suite de cet exercice, que val
est Ă©gal Ă 16.
2. On rappelle quâun parcours infixe depuis un nĆud consiste, dans lâordre, Ă faire un parcours
infixe sur le sous arbre-gauche, afficher le nĆud puis faire un parcours infixe sur le sous-arbre
droit.
Dans le cas dâun parcours suffixe, on fait un parcours suffixe sur le sous-arbre gauche puis un
parcours suffixe sur le sous-arbre droit, avant dâafficher le nĆud.
a. Donner les valeurs dâaffichage des nĆuds dans le cas du parcours infixe de lâarbre.
b. Donner les valeurs dâaffichage des nĆuds dans le cas du parcours suffixe de lâarbre.
3. On considĂšre la classe Noeud
définie de la façon suivante en Python :
a. ReprĂ©senter lâarbre construit suite Ă lâexĂ©cution de lâinstruction suivante :
racine = Noeud(18)
racine.insere_tout([12, 13, 15, 16, 19, 21, 32, 23])
val
est Ă©gal Ă 16.
c. On considĂšre lâarbre tel quâil est prĂ©sentĂ© sur la figure 1. DĂ©terminer lâordre dâexĂ©cution des
blocs (repĂ©rĂ©s de 1 Ă 3) suite Ă lâapplication de la mĂ©thode insere(19)
au nĆud racine
de cet arbre.
4. Ăcrire une mĂ©thode recherche(self, v)
qui prend en argument un entier v
et renvoie la
valeur True
si cet entier est une Ă©tiquette de lâarbre, False
sinon.
corrigé
1.a. Il y a 4 feuilles, d'Ă©tiquette 12, val
, 21 et 32.
1.b. Le sous-arbre gauche du nĆud 23 est 19-21.
1.c. La hauteur de l'arbre est 4. Sa taille est 9.
1.d. Les valeurs possibles de val
sont 16 et 17.
2.a. Parcours infixe : 12-13-15-16-18-19-21-23-32
2.b. Parcours suffixe : 12-13-16-15-21-19-32-23-18
3.a.
3.b.
racine = Noeud(18)
racine.insere([15, 13, 12, 16, 23, 32, 19, 21])
3.c. Bloc 3 - Bloc 2 - Bloc 1
4.
đ Script Python | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
Exercice 4
2021, MĂ©tropole Candidats Libres 2
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.
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.
1.a. Quelle est la taille de lâarbre ci-dessus ?
1.b. Quelle est la hauteur de lâarbre ci-dessus ?
corrigé
1.a. La taille de l'arbre est 7.
1.b. La hauteur de l'arbre est 4.
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.
corrigé
2.
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é.
đ Script Python | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
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)
corrigé
3.
4. Pour calculer la hauteur dâun arbre non vide, on a Ă©crit la mĂ©thode ci-dessous dans la classe Noeud.
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
hauteur
de la classe Arbre
qui renvoie la hauteur de
lâarbre.
corrigé
4.
đ Script Python | |
---|---|
1 2 |
|
5. Ăcrire les mĂ©thodes taille
des classes Noeud
et Arbre
permettant de calculer
la taille dâun arbre.
corrigé
5.
MĂ©thode taille
de la classe Noeud
:
đ Script Python | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
taille
de la classe Arbre
:
đ Script Python | |
---|---|
1 2 |
|
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 \(â\) est \(2^h - 1\).
6.a Quelle est la taille minimale, notée min
dâun arbre binaire de recherche
« bien construit » de hauteur \(â\) ?
corrigé
6.a. La configuration minimale d'un arbre bien construit de hauteur \(h\) peut ĂȘtre :
La taille minimale min
est donc Ă©gale Ă \(2^{h-1}\).
6.b Ăcrire la mĂ©thode bien_construit
demandée.
corrigé
6.b. Intuitivement, un arbre est mal construit si sa hauteur est trop grande par rapport à sa taille (trop étiré).
Donc un arbre est mal construit si sa taille est trop petite par rapport Ă sa hauteur.
Donc un arbre de taille \(t\) et de hauteur \(h\) est mal construit si \(t < 2^{h-1}\), puisqu'on a démontré que \(2^{h-1}\) était la taille minimale.
Pour tester si un arbre est bien construit, on va donc juste vérifier que \(t \geqslant 2^{h-1}\) :
đ Script Python | |
---|---|
1 2 3 |
|
Exercice 5
2021, Polynésie
Cet exercice traite principalement du thÚme « algorithmique, langages et programmation » et en particulier les arbres binaires de recherche. La premiÚre partie aborde les arbres en mode débranché via l'application d'un algorithme sur un exemple. La suivante porte sur la programmation orientée objet. La derniÚre partie fait le lien avec les algorithmes de tri.
Partie A : Ătude d'un exemple
Considérons l'arbre binaire de recherche ci-dessous :
Q1. Indiquer quelle valeur a le nĆud racine et quels sont les fils de ce nĆud.
corrigé
Le nĆud racine est 5 et ses fils sont 2 et 7.
Q2. Indiquer quels sont les nĆuds de la branche qui se termine par la feuille qui a pour valeur 3.
corrigé
La branche qui se termine par la feuille 3 a pour nĆuds 5, 2 et 3.
Q3. Dessiner lâarbre obtenu aprĂšs lâajout de la valeur 6.
corrigé
Partie B : Implémentation en Python
Voici un extrait dâune implĂ©mentation en Python d'une classe modĂ©lisant un arbre binaire de recherche.
đ Script Python | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Q1. Expliquer le rĂŽle de la fonction __init__
.
corrigé
La fonction __init__
est appelée «méthode constructeur», c'est elle qui crée l'objet et le dote de tous les attributs nécessaires.
Q2. Dans cette implĂ©mentation, expliquer ce qui se passe si on ajoute un Ă©lĂ©ment dĂ©jĂ prĂ©sent dans lâarbre.
corrigé
Si on ajoute un élément déjà présent dans l'arbre, la valeur e
sera Ă©gale Ă self.valeur
(éventuellement aprÚs quelques appels récursifs). Or ce cas d'égalité n'est pas prévu par les tests : il ne se passera donc RIEN. Ceci est le comportement souhaité puisqu'on ne veut pas avoir deux valeurs identiques dans notre ABR, ainsi qu'il est rappelé au début de l'énoncé.
Q3. Recopier et complĂ©ter les pointillĂ©s ci-dessous permettant de crĂ©er lâarbre de la partie A.
arbre = ABR(.......... )
arbre.insererElement(2)
arbre.insererElement(.......... )
arbre.insererElement(7)
arbre.insererElement(.......... )
corrigé
arbre = ABR(5)
arbre.insererElement(2)
arbre.insererElement(3)
arbre.insererElement(7)
arbre.insererElement(8)
Partie C : Tri par arbre binaire de recherche
On souhaite trier un ensemble de valeurs entiĂšres distinctes grĂące Ă un arbre binaire de recherche. Pour cela, on ajoute un Ă un les Ă©lĂ©ments de lâensemble dans un arbre initialement vide. Il ne reste plus quâĂ parcourir lâarbre afin de lire et de stocker dans un tableau rĂ©sultat les valeurs dans lâordre croissant.
Q1. Donner le nom du parcours qui permet de visiter les valeurs dâun arbre binaire de recherche dans lâordre croissant.
corrigé
Le parcours qui permet de visiter les valeurs d'un ABR dans l'ordre croissant est le parcours infixe.
Q2. Comparer la complexité de cette méthode de tri avec celle du tri par insertion ou du tri par sélection.
corrigé
question difficile
Pour créer l'ABR, il faut d'abord insérer chacune des valeurs. La fonction insertion
reposant sur une division par 2 à chaque étape de la taille de l'espace de recherche, on peut dire qu'elle a une complexité logarithmique. Mais cette opération est à effectuer autant de fois qu'il y a d'éléments à insérer : il faut donc multiplier la complexité logarithmique par n
, ce qui fera donc une complexité en \(n \log(n)\).
L'algorithme de parcours infixe est lui aussi linéraire, ce qui ne change pas la complexité totale.
Cette complexité est meilleure que le tris par insertion ou sélection, qui sont de complexité quadratique.
Exercice 6
2021, Centres Ătrangers, sujet 1
Un arbre binaire est soit vide, soit un nĆud qui a une valeur et au plus deux fils (le sous-arbre gauche et le sous-arbre droit).
- X est un nĆud, sa valeur est X.valeur
- G1 est le fils gauche de X, noté X.fils_gauche
- D1 est le fils droit de X, noté X.fils_droit
Un arbre binaire de recherche est ordonné de la maniÚre suivante :
Pour chaque nĆud X,
- les valeurs de tous les nĆuds du sous-arbre gauche sont strictement infĂ©rieures Ă la valeur du nĆud X
- les valeurs de tous les nĆuds du sous-arbre droit sont supĂ©rieures ou Ă©gales Ă la valeur du nĆud X.
Ainsi, par exemple, toutes les valeurs des nĆuds G1, G2 et G3 sont strictement infĂ©rieures Ă la valeur du nĆud X et toutes les valeurs des nĆuds D1, D2 et D3 sont supĂ©rieures ou Ă©gales Ă la valeur du nĆud X.
Voici un exemple d'arbre binaire de recherche dans lequel on a stocké dans cet ordre
les valeurs : [26, 3, 42, 15, 29, 19, 13, 1, 32, 37, 30]
L'Ă©tiquette d'un nĆud indique la valeur du nĆud suivie du nom du nĆud. Les nĆuds ont Ă©tĂ© nommĂ©s dans l'ordre de leur insertion dans l'arbre ci-dessous.
'29, noeud04'
signifie que le nĆud nommĂ© noeud04
possĂšde la valeur 29.
Q1. On insĂšre la valeur 25 dans l'arbre, dans un nouveau nĆud nommĂ© nĆud11.
Recopier l'arbre binaire de recherche étudié et placer la valeur 25 sur cet arbre en coloriant en rouge le chemin parcouru.
PrĂ©ciser sous quel nĆud la valeur 25 sera insĂ©rĂ©e et si elle est insĂ©rĂ©e en fils gauche ou en fils droit, et expliquer toutes les Ă©tapes de la dĂ©cision.
Correction
25 Ă©tant plus petit que 26, on part dans son sous-arbre gauche.
25 Ă©tant plus grand que 3, on part dans son sous-arbre droit.
25 Ă©tant plus grand que 15, on part dans son sous-arbre droit.
25 Ă©tant plus grand que 19, on insĂšre 25 en tant que fils droit de 19.
Q2. PrĂ©ciser toutes les valeurs entiĂšres que lâon peut stocker dans le nĆud fils gauche du nĆud04 (vide pour l'instant), en respectant les rĂšgles sur les arbres binaires de recherche.
Correction
Les valeurs acceptables doivent ĂȘtre strictement infĂ©rieures Ă 29, et supĂ©rieures ou Ă©gales Ă 26. Ces valeurs sont donc : 26, 27 et 28.
Q3. Voici un algorithme récursif permettant de parcourir et d'afficher les valeurs de l'arbre :
Parcours(A) # A est un arbre binaire de recherche
Afficher(A.valeur)
Parcours(A.fils_gauche)
Parcours(A.fils_droit)
Q3.a. Ăcrire la liste de toutes les valeurs dans l'ordre oĂč elles seront affichĂ©es.
Correction
Les valeurs seront affichées dans l'ordre suivant : 26-3-1-15-13-19-25-42-29-32-30-37
Q3.b. Choisir le type de parcours d'arbres binaires de recherche réalisé parmi les propositions suivantes : Préfixe, Suffixe ou Infixe.
Correction
On reconnait un parcours préfixe.
Q4. En vous inspirant de lâalgorithme prĂ©cĂ©dent, Ă©crire un algorithme Parcours2 permettant de parcourir et d'afficher les valeurs de l'arbre A dans l'ordre croissant.
Correction
Pour afficher les valeurs d'un ABR dans un ordre croissant, il faut utiliser un parcours infixe. Un algorithme rĂ©cursif de parcours infixe peut ĂȘtre celui-ci:
Parcours2(A) # A est un arbre binaire de recherche
Parcours2(A.fils_gauche)
Afficher(A.valeur)
Parcours2(A.fils_droit)