Eu acho que existem várias razões pelas quais não existem árvores STL. Principalmente Árvores são uma forma de estrutura de dados recursiva que, como um contêiner (lista, vetor, conjunto), possui uma estrutura fina muito diferente, o que torna as escolhas corretas complicadas. Eles também são muito fáceis de construir de forma básica usando o STL.
Uma árvore enraizada finita pode ser vista como um contêiner que possui um valor ou carga útil, por exemplo, uma instância de uma classe A e uma coleção possivelmente vazia de (sub) árvores enraizadas; as árvores com uma coleção vazia de subárvores são consideradas folhas.
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
{};
É preciso pensar um pouco sobre o design do iterador etc. e quais operações de produto e coproduto se permite definir e ser eficiente entre árvores - e o STL original deve ser bem escrito - para que o conjunto vazio, o vetor ou o contêiner de lista seja realmente vazio de qualquer carga útil no caso padrão.
As árvores desempenham um papel essencial em muitas estruturas matemáticas (veja os artigos clássicos de Butcher, Grossman e Larsen; também os artigos de Connes e Kriemer, para exemplos de como podem ser unidos e como são usados para enumerar). Não é correto pensar que o papel deles é simplesmente facilitar outras operações. Em vez disso, eles facilitam essas tarefas devido ao seu papel fundamental como estrutura de dados.
No entanto, além das árvores, também existem "co-árvores"; acima de tudo, as árvores têm a propriedade de que, se você excluir a raiz, excluirá tudo.
Considere os iteradores na árvore, provavelmente eles seriam realizados como uma simples pilha de iteradores, para um nó e seu pai, ... até a raiz.
template<class TREE>
struct node_iterator : std::stack<TREE::iterator>{
operator*() {return *back();}
...};
No entanto, você pode ter quantos quiser; coletivamente, formam uma "árvore", mas onde todas as setas fluem na direção da raiz, essa co-árvore pode ser iterada através de iteradores em direção ao iterador e raiz triviais; no entanto, ele não pode ser navegado entre ou para baixo (os outros iteradores não são conhecidos por ele) nem o conjunto de iteradores pode ser excluído, exceto acompanhando todas as instâncias.
As árvores são incrivelmente úteis, possuem muita estrutura, o que torna um sério desafio obter a abordagem definitivamente correta. Na minha opinião, é por isso que eles não são implementados no STL. Além disso, no passado, eu vi pessoas se tornarem religiosas e encontrar a idéia de um tipo de contêiner contendo instâncias de seu próprio tipo desafiador - mas elas precisam encarar - é isso que um tipo de árvore representa - é um nó que contém um coleção possivelmente vazia de árvores (menores). O idioma atual permite isso sem desafio, desde que o construtor padrão container<B>
não aloque espaço no heap (ou em qualquer outro lugar) para um B
, etc.
Eu ficaria satisfeito se isso, em boa forma, encontrasse seu caminho no padrão.