Casi todos los proyectos que tienen algún modelo o documento editable tendrán una estructura jerárquica. Puede ser útil implementar el 'nodo jerárquico' como una clase base para diferentes entidades. A menudo, la lista enlazada (hermano menor, segundo modelo) es la forma natural en que crecen muchas bibliotecas de clases, sin embargo, los niños pueden ser de diversos tipos, y probablemente un " modelo de objeto " no es lo que consideramos cuando hablamos de árboles en general.
Mi implementación favorita de un árbol (nodo) de su primer modelo es una línea (en C #):
public class node : List<node> { /* props go here */ }
Herede de una lista genérica de su propio tipo (o herede de cualquier otra colección genérica de su propio tipo). Caminar es posible en una dirección: formar la raíz hacia abajo (los artículos no conocen a sus padres).
Árbol solo para padres
Otro modelo que no mencionó es el que cada niño tiene una referencia a su padre:
null
|
+---------+---------------------------------+
| parent |
| root |
+-------------------------------------------+
| | |
+---------+------+ +-------+--------+ +--+-------------+
| parent | | parent | | parent |
| node 1 | | node 2 | | node 3 |
+----------------+ +----------------+ +----------------+
Recorrer este árbol solo es posible al revés, normalmente todos estos nodos se almacenarán en una colección (matriz, tabla hash, diccionario, etc.) y se ubicará un nodo buscando en la colección criterios distintos de la posición jerárquica en el árbol que normalmente no sería de importancia primordial.
Estos árboles solo para padres se ven generalmente en aplicaciones de bases de datos. Es bastante fácil encontrar los hijos de un nodo con las instrucciones "SELECT * WHERE ParentId = x". Sin embargo, rara vez los encontramos transformados en objetos de clase árbol-nodo como tales. En las aplicaciones con estado completo (de escritorio), pueden incluirse en controles existentes de nodo de árbol. En aplicaciones sin estado (web), incluso eso puede ser poco probable. He visto que las herramientas de generador de clases de mapeo ORM arrojan errores de desbordamiento de pila al generar clases para tablas que tienen una relación con ellos mismos (risas), por lo que tal vez estos árboles no son tan comunes después de todo.
árboles navegables bidireccionales
Sin embargo, en la mayoría de los casos prácticos, es conveniente tener lo mejor de ambos mundos. Nodos que tienen una lista de hijos y además conocen a sus padres: árboles navegables bidireccionales.
null
|
+--------------------+--------------------+
| parent |
| root |
| child1 child2 child3 |
+--+------------------+----------------+--+
| | |
+---------+-----+ +-------+-------+ +---+-----------+
| parent | | parent | | parent |
| node1 | | node2 | | node3 |
| child1 child2 | | child1 child2 | | child1 child2 |
+--+---------+--+ +--+---------+--+ +--+---------+--+
| | | | | |
Esto trae muchos más aspectos a considerar:
- ¿Dónde implementar la vinculación y desvinculación de los padres?
- deje que la lógica de negocios se encargue y deje el aspecto fuera del nodo (¡lo olvidarán!)
- los nodos tienen métodos para crear hijos (no permite reordenar) (elección de Microsofts en su implementación System.Xml.XmlDocument DOM, que casi me volvió loco cuando lo encontré por primera vez)
- Los nodos toman un padre en su constructor (no permite reordenar)
- en todos los métodos add (), insert () y remove () y sus sobrecargas de los nodos (generalmente mi elección)
- Persistencia
- Cómo caminar por el árbol cuando persiste (omita los enlaces de los padres, por ejemplo)
- Cómo reconstruir el enlace bidireccional después de la deserialización (configurar a todos los padres nuevamente como una acción posterior a la deserialización)
- Notificaciones
- Mecanismos estáticos (IsDirty flag), ¿manejan recursivamente en propiedades?
- Eventos, burbujean a través de los padres, a través de los niños, o en ambos sentidos (considere la bomba de mensajes de Windows, por ejemplo).
Ahora para responder a la pregunta , los árboles navegables bidireccionales tienden a ser (en mi carrera y campo hasta ahora) los más utilizados. Algunos ejemplos son la implementación de Microsoft System.Windows.Forms.Control o System.Web.UI.Control en el marco .Net, pero también cada implementación de DOM (Modelo de objetos de documento) tendrá nodos que conozcan a sus padres, así como una enumeración. de sus hijos. La razón: facilidad de uso sobre facilidad de implementación. Además, generalmente son clases base para clases más específicas (XmlNode puede ser la base de las clases Tag, Attribute y Text) y estas clases base son lugares naturales para colocar arquitecturas genéricas de serialización y manejo de eventos.
Los árboles se encuentran en el corazón de muchas arquitecturas, y poder navegar libremente significa poder implementar soluciones más rápido.