Por que não há classe Tree <T> no .NET?

87

A biblioteca de classes base em .NET tem algumas estruturas de dados excelentes para coleções (Lista, Fila, Pilha, Dicionário), mas estranhamente ela não contém nenhuma estrutura de dados para árvores binárias. Essa é uma estrutura extremamente útil para certos algoritmos, como aqueles que tiram proveito de diferentes caminhos de passagem. Estou procurando uma implementação gratuita escrita corretamente.

Estou simplesmente cego e não o encontro ... está enterrado algures no BCL? Se não, alguém pode recomendar uma biblioteca C # / .net gratuita ou de código aberto para árvores binárias? De preferência um que use genéricos.

EDIT: Para esclarecer o que estou procurando. Não estou interessado em coleções de dicionário ordenadas que usam internamente uma árvore. Na verdade, estou interessado em uma árvore binária - uma que expõe sua estrutura para que você possa fazer coisas como extrair subárvores ou realizar travessia pós-correção nos nós. Idealmente, essa classe poderia ser estendida para fornecer os comportamentos de árvores especializadas (ou seja, vermelho / preto, AVL, balanceado, etc).

LBushkin
fonte
Acordado. Ocasionalmente, tenho a necessidade de encontrar (no tempo O (Log N)) os dois nós que limitam um valor (quando o valor não é encontrado na coleção). Por exemplo, a coleção (árvore) contém 13 e 17 (entre outros) e estou procurando o maior menor que e menor maior que 16. Uma árvore poderia fazer isso, mas Dicionários, listas classificadas e tabelas hash levam O (N) .
Les

Respostas:

31

Você está certo, não há nada no BCL. Suspeito que isso seja porque a escolha de usar uma árvore normalmente é um detalhe de implementação e, caso contrário, é uma forma não convencional de acessar dados. Ou seja, você não diz "binary-search-for element # 37"; em vez disso, você diz "pegue o elemento 37".

Mas você já deu uma olhada no C5 ? É muito prático e tem várias implementações de árvore ( 1 , 2 , 3 ).

John Feminella
fonte
3
C5 suporta árvores Red Black, não B-Tree. São diferenças das quais as pessoas devem estar cientes. B-Tree é mais ideal para uma árvore baseada em disco ou uma árvore baseada em memória grande. Mais nós são mantidos na mesma localidade para que você obtenha melhor desempenho do cache do processador e seja mais rápido para ler e gravar no disco.
AnthonyLambert,
68

Você pode definir o seu próprio:

public class MyTree<K, V> : Dictionary<K, MyTree<K, V>>
{
    public V Value { get; set; }
}

Ou sem chave:

public class MyTree<V> : HashSet<MyTree<V>>
{
    public V Value { get; set; }
}
Jason
fonte
No entanto, isso requer que você saiba com quantos níveis de árvore você lidará em tempo de compilação, estou errado?
Veverke
1
Não, o compilador C # oferece suporte a essa sintaxe.
Jason,
2
Esteja ciente de que os elementos não são ordenados desta forma
Sebastian
@Veverke Talvez você esteja pensando em modelos C ++. Os genéricos .NET são tipos de tempo de execução.
Tom Blodget
Estou curioso. Como você usa isso? Praticamente? Qualquer amostra?
Syaiful Nizam Yahya
39

O que você gostaria de tal implementação?

Árvore binária? Vermelho preto? Árvore Radix? Árvore B? R-tree? R * -tree?

Uma árvore é mais um padrão do que uma estrutura de dados, e eles tendem a ser usados ​​onde o desempenho é importante (portanto, os detalhes de implementação provavelmente também importam). Se o BCL incluiu algum tipo de classe de árvore, você só teria que lançar a sua própria de qualquer maneira

Alun Harford
fonte
1
Melhor resposta para a parte "por quê" da pergunta.
Joel Coehoorn
E essas são apenas as árvores de busca. Existem também árvores de expressão, árvores de decisão, ...
Henk Holterman
Na verdade, os detalhes de implementação são importantes. No meu caso, estou procurando implementar alguns algoritmos que executariam diferentes travessias (infix, postfix) em um conjunto organizado de dados como parte de uma série de transformações. Uma estrutura em árvore é a maneira mais elegante de resolver meu problema.
LBushkin
11
Em um universo paralelo, alguém está se perguntando: "Por que não há tipos de lista em .Net?", E obtém a resposta: "O que você gostaria de tal implementação? Uma matriz? Uma lista vinculada? Uma fila? A dicionário?" Eu acho que esta é uma resposta não sequitur.
rymdsmurf de
12

SortedSet<T>é implementado como uma árvore de pesquisa binária ref . SortedDictionary<TKey, TValue>faz uso interno de SortedSet<T>uma árvore de pesquisa binária ref .

Matt Brunell
fonte
5
Infelizmente, essas são simplesmente implementações de mapas e listas ordenados. Nenhum dos dois é útil para reutilização como árvore binária - essas estruturas de árvore são simplesmente um detalhe de implementação da coleção. Na verdade, estou procurando uma classe que expõe a estrutura da árvore.
LBushkin
9

Não, não existe nenhum Tree<T>tipo " parecido com" no BCL (algo que sempre me intrigou), mas aqui está um bom artigo que o ajudará a implementar o seu próprio tipo em C #.

Eu acho que você poderia argumentar que as estruturas de dados baseadas em árvore são menos comumente usadas no tipo de aplicativo para o qual o .NET é normalmente usado (aplicativos de negócios, aplicativos de movimentação de dados, etc.). Mesmo assim, concordo com você, é estranho que o BCL não tenha nenhuma implementação.

Andrew Hare
fonte
-5

Há um TreeNode que você pode usar. Não é genérico e está escondido nos formulários do Windows e é usado com o controle de visualização em árvore, mas você também pode usá-lo em outro lugar.

Joel Coehoorn
fonte
Sim, mas tem apenas uma propriedade Tag de System.Object ype. Nenhum parâmetro <T> genérico
Henk Holterman
3
Sempre me sinto estranho em fazer coisas assim. É menos visível com o seu exemplo específico, mas se as pessoas reaproveitarem rotineiramente as classes de, digamos, dependências, isso pode resultar em dependências difíceis de explicar e pode causar problemas se a classe readaptada mudar de maneira inesperada versões de dependência.
Paul Morie
4
Qual seria o lucro de usá-lo? Um nó de árvore geralmente não possui nenhuma funcionalidade relevante. Ele apenas contém referências a filhos e, eventualmente, a um pai. Não há razão para usar indevidamente uma classe System.Windows.Forms para isso! Escreva você mesmo - em um minuto ou menos.
user492238