Je pense qu'il y a plusieurs raisons pour lesquelles il n'y a pas d'arbres STL. Les arbres sont principalement une forme de structure de données récursive qui, comme un conteneur (liste, vecteur, ensemble), a une structure fine très différente qui rend les choix corrects délicats. Ils sont également très faciles à construire sous forme de base à l'aide de la STL.
Un arbre enraciné fini peut être considéré comme un conteneur qui a une valeur ou une charge utile, par exemple une instance d'une classe A et, une collection éventuellement vide d'arbres (sous) enracinés; les arbres avec une collection vide de sous-arbres sont considérés comme des feuilles.
template<class A>
struct unordered_tree : std::set<unordered_tree>, A
{};
template<class A>
struct b_tree : std::vector<b_tree>, A
{};
template<class A>
struct planar_tree : std::list<planar_tree>, A
{};
Il faut penser un peu à la conception de l'itérateur, etc. et aux opérations de produit et de coproduit qui permettent de définir et d'être efficace entre les arbres - et la STL d'origine doit être bien écrite - de sorte que l'ensemble vide, le vecteur ou le conteneur de liste soit vraiment vide de toute charge utile dans le cas par défaut.
Les arbres jouent un rôle essentiel dans de nombreuses structures mathématiques (voir les articles classiques de Butcher, Grossman et Larsen; aussi les articles de Connes et Kriemer pour des exemples de leur assemblage, et comment ils sont utilisés pour énumérer). Il n'est pas correct de penser que leur rôle est simplement de faciliter certaines autres opérations. Ils facilitent plutôt ces tâches en raison de leur rôle fondamental en tant que structure de données.
Cependant, en plus des arbres, il existe également des «co-arbres»; les arbres ont surtout la propriété que si vous supprimez la racine, vous supprimez tout.
Considérez les itérateurs sur l'arborescence, ils seraient probablement réalisés comme une simple pile d'itérateurs, vers un nœud et son parent, ... jusqu'à la racine.
template<class TREE>
struct node_iterator : std::stack<TREE::iterator>{
operator*() {return *back();}
...};
Cependant, vous pouvez en avoir autant que vous le souhaitez; collectivement, ils forment un "arbre" mais là où toutes les flèches circulent dans la direction de la racine, ce co-arbre peut être itéré à travers des itérateurs vers l'itérateur et la racine triviaux; cependant, il ne peut pas être parcouru à travers ou vers le bas (les autres itérateurs ne le connaissent pas), ni l'ensemble des itérateurs ne peut être supprimé sauf en gardant une trace de toutes les instances.
Les arbres sont incroyablement utiles, ils ont beaucoup de structure, ce qui en fait un défi sérieux pour obtenir l'approche définitivement correcte. À mon avis, c'est pourquoi ils ne sont pas mis en œuvre dans la STL. De plus, dans le passé, j'ai vu des gens devenir religieux et trouver l'idée d'un type de conteneur contenant des instances de son propre type difficile - mais ils doivent y faire face - c'est ce que représente un type d'arbre - c'est un nœud contenant un collection éventuellement vide d'arbres (plus petits). Le langage actuel le permet sans problème en fournissant le constructeur par défaut pour container<B>
n'alloue pas d'espace sur le tas (ou n'importe où ailleurs) pour un B
, etc.
Pour ma part, je serais ravi que cela, dans une bonne forme, trouve sa place dans la norme.