DS 2 (MPSI option 2021-2022) — Arbres de Fibonacci¶
Devoir surveillé · MPSI (option informatique) · 2021-2022 · partie II du DS 2 (2 h au total)
Cours : Arbres binaires
Autres parties : I, III, IV. Fibonacci et Zeckendorf
II. Arbres de Fibonacci¶
On considère le type Caml suivant pour représenter des arbres binaires stricts :
type arbre =
| Feuille
| Noeud of arbre * arbre
Question 5
Écrire une fonction nb_feuilles : arbre -> int qui renvoie le
nombre de feuilles d'un arbre.
Corrigé
let rec nb_feuilles a =
match a with
| Feuille -> 1
| Noeud (g, d) -> nb_feuilles g + nb_feuilles d
On définit les arbres de Fibonacci \((A_n)_{n\in\N}\) de la manière récursive suivante :
- \(A_0\) et \(A_1\) sont des feuilles ;
- si \(n \ge 2\), \(A_n\) est un nœud comportant \(A_{n-1}\) comme fils gauche et \(A_{n-2}\) comme fils droit.
Question 6
Dessiner les arbres \(A_2\), \(A_3\), \(A_4\) et \(A_5\).
Corrigé
Les nœuds sont représentés par des disques et les feuilles par des carrés.
Question 7
Écrire en Caml une fonction arbre_fibonacci : int -> arbre
telle que l'appel arbre_fibonacci n renvoie l'arbre \(A_n\).
Corrigé
let rec arbre_fibonacci n =
if n <= 1
then Feuille
else Noeud (arbre_fibonacci (n-1), arbre_fibonacci (n-2))
Question 8
Montrer que la complexité de cette fonction est en \(O(2^n)\).
On pourra remarquer qu'en dehors des appels récursifs tout se fait en temps constant et chercher à majorer le nombre d'appels récursifs.
Corrigé
On procède comme l'explication et on note \(C_n\) le nombre d'appels récursifs pour calculer le \(n\)-ième arbre. On a \(C_0 = C_1 = 0\) et \(C_n = 2 + C_{n-1} + C_{n-2}\).
Comme l'appel pour \(n\) nécessite de résoudre l'appel pour \(n-1\), on a nécessairement \(C_n\) croissante et \(C_n \le 2 (1 + C_{n-1})\) donc \(C_n + 2 \le 2 (C_{n-1} + 2)\) et par une récurrence rapide \(C_n + 2 \le 2^n\) donc \(C_n \le 2^n - 2 = O(2^n)\).
Question 9
Quelle est, pour \(n \in \N\), la hauteur de l'arbre \(A_n\) ? Justifier rigoureusement.
Corrigé
On a \(h(A_0) = h(A_1) = 0\) et pour \(n \ge 2\), \(h(A_n) = 1 + \max (h(A_{n-1}), h(A_{n-2}))\). On en déduit que \(h(A_n)\) est croissante et donc que \(h(A_n) = 1 + h(A_{n-1})\) d'où \(h(A_n) = n-1\) pour \(n \ge 1\).
Question 10
Exprimer le nombre de feuilles de \(A_n\) à l'aide des nombres de la suite de Fibonacci \((F_n)_{n\in\N}\).
Corrigé
De même si \(f(A)\) est le nombre de feuilles de \(A\), on a \(f(A_0) = f(A_1) = 1\) et \(f(A_n) = f(A_{n-1}) + f(A_{n-2})\). Donc \(f(A_n) = F_{n+1}\) : mêmes deux premières valeurs et même récurrence.
Question 11
Exprimer le nombre de nœuds de \(A_n\) à l'aide des nombres de la suite de Fibonacci \((F_n)_{n\in\N}\).
Corrigé
On note \(N(A)\) le nombre de nœuds de \(A\).
On a \(N(A_0) = N(A_1) = 0\) et \(N(A_n) = 1+ N(A_{n-1}) + N(A_{n-2})\).
En posant \(u_n = N(A_n) + 1\), on a pour \(n \ge 2\), \(u_n = u_{n-1} + u_{n-2}\) et \(u_0 = u_1 = 1\). Donc \(u_n = F_{n+1}\) et \(N(A_n) = F_{n+1} - 1\).
Question 12
Montrer que les arbres de Fibonacci sont équilibrés : en tout nœud de l'arbre les hauteurs des sous-arbres gauche et droit diffèrent au plus de 1.
Corrigé
C'est une conséquence directe du calcul de \(h(A_n) = n-1\) et de la définition.
Question 13
Écrire en Caml une fonction arbre_fibonacci_bis : int -> arbre
de complexité \(O(n)\). Comment est-il possible d'avoir une fonction de
complexité linéaire en \(n\) qui crée un arbre de taille exponentielle en \(n\) ?
Corrigé
let arbre_fibonacci_bis n =
let f = ref Feuille in
let f' = ref Feuille in
for i = 1 to n do
let t = !f' in
f' := Noeud (!f', !f);
f := t
done;
!f
En fait, quand on écrit Noeud (!f', !f) on ne copie pas les arbres, on
se contente d'y faire référence. En mémoire, les valeurs ne sont pas
dupliquées.