Cours alternatif d’OCaml

Logo OCaml
IX — Les arbres

Qu’est-ce qu’un arbre ?

Un arbre est une plante ligneuse terrestre comportant un tronc sur lequel s’insèrent des branches ramifiées portant le feuillage dont l’ensemble forme le houppier, appelé aussi couronne.

Plus sérieusement, un arbre est une structure de donnée assez courante en informatique. Ce nom a été choisi parce qu’il y a des ressemblances entre l’organisation d’un vrai arbre et d’un arbre en informatique :

Les arbres sont donc des structures récursives : on enchaîne les embranchements jusqu’à atteindre une feuille. C’est un peu comme des listes, sauf qu’à chaque fois au lieu de continuer avec un seul élément, on a plusieurs possibilités.

Cette structure de données est très utile dans certains cas, que ce soit pour représenter des hiérarchies, ou pour permettre de réaliser certains algorithmes de manière efficace.

Voici un schéma d’un arbre avec deux branches à chaque embranchement :

Un arbre

Ici :

Mais cet arbre n’est qu’un exemple, on peut choisir de mettre plus ou moins de branches à chaque embranchement.

En OCaml, on enregistrera des données au niveau de chaque feuille et éventuellement au niveau de chaque embranchement.

Encore un peu théorie : le vocabulaire des arbres

Les arbres ont un vocabulaire particulier1 pour les qualifier :

Ça fait beaucoup de nouveaux mots, mais ne vous inquiétez pas, on s’habitue.

La pratique : définition d’un arbre en OCaml

On va essayer de représenter l’arbre schématisé au-dessus avec un type OCaml. On va pour cela utiliser un type somme récursif.

type arbre =
  | Feuille
  | Noeud of arbre * arbre

Ici, chaque nœud peut amener à deux enfants. Si on veut stocker des données à chaque feuille, on peut rendre ce type polymorphe, et ajouter des données au constructeur Feuille :

type 'a arbre =
  | Feuille of 'a
  | Noeud of 'a arbre * 'a arbre

On peut aussi décider de rajouter des données à chaque nœud :

type 'a arbre =
  | Feuille of 'a
  | Noeud of 'a * 'a arbre * 'a arbre

Et on peut aussi ajouter un nombre quelconque d’enfants à chaque nœud, avec une liste :

type 'a arbre =
  | Feuille of 'a
  | Noeud of 'a * 'a arbre list

Bref, il n’y a pas qu’une seule façon de modéliser un arbre, et selon le problème qu’on cherche à résoudre on n’utilisera pas tout à fait le même type.

Voici un exemple pour modéliser un arbre généalogique, où les données sont les noms des personnes :

type arbre_gene =
  | Ancetre of string (* On est remonté tellement loin qu’on ne se souvient plus qui était les parents de cette personne *)
  | Personne of string * arbre_gene * arbre_gene (* On considère que tout le monde a deux parents *)

(* L’abre généalogique qui part de Jade et qui remonte jusqu’à ses grands parents *)
let arbre_de_jade =
  Personne(
    "Jade",
    Personne(
      "Jeanne",
      Ancetre("Jeanine"),
      Ancetre("Jean")
    ),
    Personne(
      "Jules",
      Ancetre("Julien"),
      Ancetre("Julie")
    )
  )

Ce n’est qu’un exemple d’utilisation des arbres, on peut aussi s’en servir pour représenter une arborescence de fichiers dans un disque dur (les embranchements sont les dossiers et les feuilles les fichiers), une hiérarchie (chaque embranchement correspond à un supérieur hiérarchique, et les feuilles à ceux qui sont en bas de l’échelle), etc.

Dans la suite, on va surtout parler d’arbres binaires, en particulier pour les algorithmes de recherche dans des listes.


  1. Parfois connu sous le nom de langage des plantes.