Exercice 0 - Arbres binaires
-
Problème 0 : Implémentez les arbres binaires comme un type algébrique appelé
binary_tree. -
Problème 1 : Décrivez les valeurs de
binary_treecorrespondant aux arbres suivants.
-
Problème 2 : Implémentez une fonction
count_nodes : binary_tree -> intqui compte le nombre de noeuds dans un arbre donné. -
Problème 3 : Pouvez-vous penser à une version plus efficace ?
-
Problème 4 : Reformulez
binary_treeen un nouveau type de données algébrique appelédecorated_binary_tree, paramétré par une variable de type'a, de telle sorte que chaque noeud et chaque feuille stocke une valeur de type'a. -
Problème 5 : Décrivez les valeurs de
decorated_binary_treecorrespondant aux arbres suivants:
-
Problème 6 : Implémentez une fonction
tree_sum : int decorated_binary_tree -> intqui additionne les valeurs stockées dans les noeuds et les feuilles d'un arbre en entrée. -
Problème 7 : Pouvez-vous penser à une version plus efficace ?
-
Problème 8 : Implémentez une fonction
search_tree : 'a decorated_binary_tree -> 'a -> boolqui recherche dans l'arbre d'entrée un élément correspondant à son second argument et renvoie true s'il en trouve un, sinon false. -
Problème 9 : Pouvez-vous imaginer une version plus efficace ?
Dans ce qui suit, le type internally_decorated_tree est donné par :
type 'a internally_decorated_tree =
Leaf
| Node of 'a * 'a internally_decorated_tree * 'a
internally_decorated_tree
Exercice 1 - Map sur les arbres
Utilisez la fonction map sur les arbres dans vos solutions à tous les problèmes suivants.
- Problème 0: Implémentez une fonction
succ : int internally_decorated_tree -> int internally_decorated_treetelle que la valeur d'un noeud desucc tsoit le successeur de la valeur du noeud correspondant det.
Exercice 1: Fold sur les arbres
Utilisez la fonction fold sur les arbres dans vos solutions à tous les problèmes suivants.
-
Problème 0: Implémentez une fonction
tree_sum : int internally_decorated_tree -> inttelle quetree_sum tsoit égale à la somme des valeurs de tous les noeuds det. -
Problème 1: Implémentez une fonction
tree_prod : int internally_decorated_tree -> inttelle quetree_prod tsoit égal au produit des valeurs de tous les noeuds det. -
Problème 2: Implémentez une fonction
search_in_tree : int internally_decorated_tree -> int -> booltelle quesearch_in_tree t eestvraisieapparaît comme la valeur de n'importe quel noeud det.
Devoir à rendre avant le 15 octobre 2025, 23h59, heure de Paris:
- Problème 0 : La sérialisation d'un arbre est une liste qui contient tous les éléments de
l'arbre dans un ordre donné. Un algorithme récursif pour sérialiser un arbre
binaire (non vide) est le suivant :
- Soit \(v\) la valeur de la racine actuelle, \(l\) le sous-arbre de gauche, et \(r\) le sous-arbre de droite. Soit \(s_v = [v]\) une liste dont le seul élément est la valeur \(v\) de la racine courante, \(s_l\) la sérialisation du sous-arbre gauche \(l\), et \(s_r\) la sérialisation du sous-arbre droit \(r\). Les valeurs \(s_l\) et \(s_r\) sont calculées récursivement.
- L'algorithme renvoie ensuite la sérialisation de l'arbre entier en
concaténant les \(s_v, s_l,s_r\) dans l'un des trois ordres suivants :
- D'abord \(s_v\), puis \(s_l\), puis \(s_r\) (ordre préfixe).
- D'abord \(s_l\), puis \(s_r\), puis \(s_v\) (ordre postfixe).
- D'abord \(s_l\), puis \(s_v\), puis \(s_r\) (ordre infixe).
serialise_prefix,serialise_postfixetserialise_infixen OCaml (en utilisant la fonction fold pour les arbres que nous avons écrite en classe), toutes de type'a internally_decorated_tree -> 'a listqui exécutent les trois variantes (préfixe, postfixe et infixe) de l'algorithme ci-dessus sur les valeurs du type'a internally_decorated_treedéfini plus haut. Exemples de deux arbres (unint internally_decorated_treeet unstring internally_decoracted_tree) et les résultats des trois fonctions mentionnées ci-dessus appliquées à chacun d'eux :
# (* définissant les exemples *);;
# let first_example = Node ("a",
Node ("b", Leaf,
Node ("c", Leaf, Leaf)),
Node ("d",
Node ("e", Leaf, Leaf), Leaf));;
val first_example : string internally_decorated_tree =
Node ("a",
Node ("b", Leaf,
Node ("c", Leaf, Leaf)),
Node ("d",
Node ("e", Leaf, Leaf),
Leaf))
# let second_example = Node ("0",
Node ("1",
Node ("2", Leaf, Leaf),
Node ("3", Leaf,
Node ("4", Leaf, Leaf))),
Node ("5",
Node ("6", Leaf, Leaf), Leaf));;
val second_example : string internally_decorated_tree =
Node ("0",
Node ("1",
Node ("2", Leaf, Leaf),
Node ("3", Leaf,
Node ("4", Leaf, Leaf))),
Node ("5",
Node ("6", Leaf, Leaf),
Leaf))
# (* appliquant nos fonctions aux deux exemples *);;
# serialise_prefix first_example;;
- : string list = ["a"; "b"; "c"; "d"; "e"]
# serialise_prefix second_example;;
- : string list = ["0"; "1"; "2"; "3"; "4"; "5"; "6"]
# serialise_infix first_example;;
- : string list = ["b"; "c"; "a"; "e"; "d"]
# serialise_infix second_example;;
- : string list = ["2"; "1"; "3"; "4"; "0"; "6"; "5"]
# serialise_postfix first_example;;
- : string list = ["c"; "b"; "e"; "d"; "a"]
# serialise_postfix second_example;;
- : string list = ["2"; "4"; "3"; "1"; "6"; "5"; "0"]
Ecrivez une fonction tree_height : 'a internally_decorated_tree ->
int qui calcule la hauteur d'un arbre donné en utilisant la fonction fold
pour les arbres que nous avons écrite en classe pour implémenter l'algorithme
récursif suivant :
1. Calculez récursivement la hauteur $h_l$ du sous-arbre gauche et la
hauteur $h_r$ du sous-arbre droit.
2. La hauteur de l'arbre entier est alors $1 + max(h_l, h_r)$. </ul>
Exemples de résultats attendus (en réutilisant les exemples du problème
précédent) : # tree_height first_example;;
- : int = 3 # tree_height second_example;;
- : int = 4