Implémentation simpliste des arbres binaires de recherche

Cette implémentation permet de manipuler des arbres binaires complets, c'est-à-dire où tous les nœuds ont zéro ou deux fils. Les nœuds internes ont deux fils et les feuilles ont aucun fils. Seuls les nœuds internes ont une valeur. Un arbre ayant n nœuds internes a n+1 feuilles. L'arbre vide a aucun nœud interne et une seule feuille.

Arbres

Chaque arbre est représenté par un objet de la classe Tree qui possède une référence sur la racine de l'arbre. Si l'arbre est vide, cette racine est une feuille et dans le cas contraire, c'est un nœud interne. La classe Tree fournit deux méthodes d'affichage. La première méthode toString() retourne une chaîne qui donne une représentation parenthèsée d'un arbre. La méthode prettyPrint() offre un affichage agréable de l'arbre.

Les nœuds internes sont représentés par des objets de la classe InternalNode et les feuilles sont représentés par des objets de la classe EmptyNode. Ces deux classes implémentent l'interface Node.

Recherche et insertion

Les arbres implémentés sont des arbres binaires de recherche. Les valeurs sont mises dans les nœuds de telle manière que pour tout nœud n,

Pour que les valeurs mises dans les arbres puissent être comparées entre elles, celles-ci doivent implémenter l'interface Comparable. Cette interface spécifie que les objets doivent avoir une méthode int compareTo(Object o). L'ajout d'une nouvelle valeur se fait par un appel à la méthode put(Comparable v) de la classe Tree. La recherche d'une valeur dans l'arbre se fait par un appel à la méthode boolean contains(Comparable o) de la classe Tree.

Parcours

Parcours en largeur

La classe Tree possède une méthode breathFirstIterator qui retourne un itérateur. Les appels successifs à la méthode next() de cet itérateur retournent les valeurs des nœuds dans l'ordre déterminé par le parcours en largeur.

Parcours en profondeur

La classe Tree possède plusieurs méthodes permettant des parcours en profondeur des arbres. Les parcours possibles sont le parcours préfixe, le parcours infixe et le parcours suffixe. Pour un arbre binaire de recherche, le parcours infixe permet de parcourir les valeurs par ordre croissant.

Les parcours en profondeur sont disponibles sous deux formes.

Sous forme d'action

La première forme utilise la notion d'action. La classe Tree possède des méthodes de parcours qui prennent en paramètre un objet de type Action. Cette interface définit une seule méthode run qui prend un objet en paramètre. Cette méthode est appliquée à chacune des valeurs des nœuds dans l'ordre déterminé par le parcours. On peut par exemple afficher toutes les valeurs des sommets en appelant une des méthode de parcours avec un objet de classe PrintAction en paramètre. La classe PrintAction implémente l'interface Action en définissant une méthode run qui appelle la méthode System.out.println avec la valeur du nœud. Les méthodes de parcours de la classe Tree sont les méthodes prefixRun(Action a), infixRun(Action a) et suffixRun(Action a). L'affichage dans l'ordre de toutes les valeurs d'un arbre t peut se faire par l'appel

  t.infixRun(new PrintAction());

Sous forme d'itérateur

La seconde forme utilise la notion d'itérateur. La classe Tree possède des méthodes qui retourne des objets qui implémente l'interface Iterator. Les appels successifs à la méthode next() de ces objets retournent les valeurs des nœuds dans l'ordre déterminé par le parcours. Les méthodes retournant les itérateurs sont les méthodes prefixIterator, infixIterator et suffixIterator. L'affichage dans l'ordre de toutes les valeurs d'un arbre t peut se faire par la boucle

  for(Iterator i = t.infixIterator(); i.hasNext();)
    System.out.println(i.next());

Les itérateurs pour les différents parcours sont réalisés par des classes internes de la classe Tree. Pour chacun des trois parcours préfixe, infixe et suffixe, la classe Tree fournit deux implémentations différentes de l'itérateur. Les méthodes prefixIterator, infixIterator et suffixIterator retournent une des deux implémentations.

Une première implémentation des parcours se fait à l'aide d'un objet de la classe GeneralIterator qui permet un parcours général de l'arbre. Les trois classes SimplePrefixIterator, SimpleInfixIterator et SimpleSuffixIterator se contente de sélectionner les premiers, deuxièmes et troisièmes passage dans chacun des nœuds dans le parcours général.

Une deuxième implémentation directe des parcours est également fourni par les classes DirectPrefixIterator, DirectInfixIterator et DirectSuffixIterator.