¿Por qué no hay una clase Tree <T> en .NET?

87

La biblioteca de clases base en .NET tiene algunas estructuras de datos excelentes para colecciones (Lista, Cola, Pila, Diccionario), pero curiosamente no contiene ninguna estructura de datos para árboles binarios. Esta es una estructura tremendamente útil para ciertos algoritmos, como los que aprovechan diferentes rutas transversales. Estoy buscando una implementación gratuita y correctamente escrita.

¿Estoy simplemente ciego y no lo encuentro ... está enterrado en algún lugar del BCL? Si no es así, ¿alguien puede recomendar una biblioteca C # / .NET gratuita o de código abierto para árboles binarios? Preferiblemente uno que emplee genéricos.

EDITAR: Para aclarar lo que estoy buscando. No me interesan las colecciones de diccionarios ordenadas que utilizan internamente un árbol. De hecho, estoy interesado en un árbol binario, uno que exponga su estructura para que pueda hacer cosas como extraer subárboles o realizar un recorrido posterior a la corrección en los nodos. Idealmente, dicha clase podría extenderse para proporcionar los comportamientos de árboles especializados (es decir, rojo / negro, AVL, equilibrado, etc.).

LBushkin
fuente
Convenido. Ocasionalmente tengo la necesidad de encontrar (en el tiempo O (Log N)) los dos nodos que unen un valor (cuando el valor no se encuentra en la colección). Por ejemplo, la colección (árbol) contiene 13 y 17 (entre otros) y estoy buscando el mayor menor que y el menor mayor que 16. Un árbol podría hacer esto, pero los diccionarios, las listas ordenadas y las tablas hash toman O (N) .
Les

Respuestas:

31

Tienes razón, no hay nada en la BCL. Sospecho que esto se debe a que la elección de utilizar un árbol suele ser un detalle de implementación y, por lo demás, es una forma poco convencional de acceder a los datos. Es decir, no dice, "binary-search-for element # 37"; en su lugar, dice, "consígame el elemento n. ° 37".

Pero, ¿ha echado un vistazo al C5 ? Es muy útil y tienen varias implementaciones de árbol ( 1 , 2 , 3 ).

John Feminella
fuente
3
C5 admite árboles Red Black, no B-Tree. Son diferencias que la gente debería conocer. B-Tree es más óptimo para un árbol basado en disco o un árbol basado en memoria grande. Se mantienen más nodos en la misma localidad para que obtenga un mejor rendimiento de la caché del procesador y sea más rápido leer y escribir en el disco.
AnthonyLambert
68

Podrías definir el tuyo propio:

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

O sin llave:

public class MyTree<V> : HashSet<MyTree<V>>
{
    public V Value { get; set; }
}
Jason
fuente
Sin embargo, esto requiere que sepas cuántos niveles de árbol manejarás en tiempo de compilación, ¿me equivoco?
Veverke
1
No, el compilador de C # admite esta sintaxis.
Jason
2
Tenga en cuenta que los elementos no están ordenados de esta manera
Sebastian
@Veverke Quizás estabas pensando en plantillas C ++. Los genéricos .NET son tipos de tiempo de ejecución.
Tom Blodget
Soy curioso. ¿Cómo usas esto? ¿Prácticamente? ¿Alguna muestra?
Syaiful Nizam Yahya
39

¿Qué le gustaría de tal implementación?

¿Árbol binario? ¿Negro rojo? ¿Árbol de radix? Árbol B? R-tree? R * -árbol?

Un árbol es más un patrón que una estructura de datos, y tienden a usarse donde el rendimiento importa (por lo que los detalles de implementación probablemente también importen). Si el BCL incluye algún tipo de clase de árbol, de todos modos solo tendrías que tirar el tuyo

Alun Harford
fuente
1
La mejor respuesta para la parte de la pregunta "por qué".
Joel Coehoorn
Y esos son solo los árboles de búsqueda. También hay árboles de expresión, árboles de decisión, ...
Henk Holterman
De hecho, los detalles de implementación son importantes. En mi caso, estoy buscando implementar algunos algoritmos que realizarían recorridos diferentes (infijo, sufijo) en un conjunto organizado de datos como parte de una serie de transformaciones. Una estructura de árbol es la forma más elegante de resolver mi problema.
LBushkin
11
En un universo paralelo, alguien se hace la pregunta: "¿Por qué no hay tipos de lista en .Net?", Y obtienen la respuesta: "¿Qué querrías de tal implementación? ¿Una matriz? ¿Una lista enlazada? ¿Una cola? ¿diccionario?" Creo que esta es una respuesta non sequitur.
rymdsmurf
12

SortedSet<T>se implementa como un árbol de búsqueda binario ref . SortedDictionary<TKey, TValue>utiliza internamente, por SortedSet<T>lo que también es un árbol de búsqueda binario ref .

Matt Brunell
fuente
5
Desafortunadamente, estas son simplemente implementaciones de mapas y listas ordenados. Ninguno de los dos es útil para su reutilización como árbol binario; estas estructuras de árbol son simplemente un detalle de implementación de la colección. De hecho, estoy buscando una clase que exponga la estructura del árbol.
LBushkin
9

No, no hay ningún tipo " Tree<T>similar" en el BCL (algo que siempre me ha desconcertado también) pero aquí hay un buen artículo que lo guiará a través de la implementación del suyo en C #.

Supongo que podría argumentar que las estructuras de datos basadas en árboles se usan con menos frecuencia en el tipo de aplicaciones para las que se usa generalmente .NET (aplicaciones comerciales, aplicaciones de movimiento de datos, etc.). Aún así, estoy de acuerdo con usted, es extraño que el BCL no tenga implementación alguna.

Andrew Hare
fuente
-5

Hay un TreeNode que puedes usar. No es genérico y está oculto en formularios de Windows y se usa con el control de vista de árbol, pero también puede usarlo en otros lugares.

Joel Coehoorn
fuente
Sí, pero solo tiene una propiedad Tag de System.Object ype. Sin parámetro genérico <T>
Henk Holterman
3
Siempre me siento raro por hacer cosas así. Es menos visible con su ejemplo específico, pero si las personas reutilizan rutinariamente las clases de, digamos, dependencias, esto puede resultar en dependencias difíciles de explicar y puede causarle problemas si la clase rediseñada cambia de una manera inesperada a través de versiones de dependencia.
Paul Morie
4
¿Cuál sería el beneficio de usarlo? Un nodo de árbol generalmente no tiene ninguna funcionalidad relevante en él. Solo contiene referencias a los hijos y, finalmente, a los padres. ¡No hay razón para hacer un mal uso de una clase System.Windows.Forms! Escríbalo usted mismo, en un minuto o menos.
user492238