obtengo el concepto detrás de trie. Pero me confundo un poco cuando se trata de implementación.¿Cuál sería una forma sensata de implementar un Trie en .NET?
La forma más obvia que podría pensar para estructurar un tipo Trie
sería tener un Trie
mantener un Dictionary<char, Trie>
interno. De hecho, he escrito uno de esta manera, y funciona, pero ... esto parece exagerado. Mi impresión es que un trie debería ser liviano, y tener un Dictionary<char, Trie>
por separado para cada nodo no me parece muy liviano.
¿Existe alguna forma más adecuada de implementar esta estructura que me falta?
ACTUALIZACIÓN: OK! Basándose en la información muy útil de Jon y leppie, esto es lo que he encontrado hasta el momento:
(1) que tienen el tipo Trie
, que tiene una _nodes
miembro privado de tipo Trie.INodeCollection
.
(2) La interfaz Trie.INodeCollection
tiene los siguientes miembros:
interface INodeCollection
{
bool TryGetNode(char key, out Trie node);
INodeCollection Add(char key, Trie node);
IEnumerable<Trie> GetNodes();
}
(3) Hay tres implementaciones de esta interfaz:
class SingleNode : INodeCollection
{
internal readonly char _key;
internal readonly Trie _trie;
public SingleNode(char key, Trie trie)
{ /*...*/ }
// Add returns a SmallNodeCollection.
}
class SmallNodeCollection : INodeCollection
{
const int MaximumSize = 8; // ?
internal readonly List<KeyValuePair<char, Trie>> _nodes;
public SmallNodeCollection(SingleNode node, char key, Trie trie)
{ /*...*/ }
// Add adds to the list and returns the current instance until MaximumSize,
// after which point it returns a LargeNodeCollection.
}
class LargeNodeCollection : INodeCollection
{
private readonly Dictionary<char, Trie> _nodes;
public LargeNodeCollection(SmallNodeCollection nodes, char key, Trie trie)
{ /*...*/ }
// Add adds to the dictionary and returns the current instance.
}
(4) Cuando un Trie
se construye primero, su miembro _nodes
es null
. La primera llamada al Add
crea un SingleNode
, y las llamadas posteriores al Add
van desde allí, de acuerdo con los pasos descritos anteriormente.
¿Tiene esto sentido? Esto se siente como una mejora en el sentido de que algo reduce el "volumen" de un Trie
(los nodos ya no son objetos completos Dictionary<char, Trie>
hasta que tengan un número suficiente de hijos). Sin embargo, también se ha vuelto significativamente más complejo. ¿Es muy complicado? ¿He tomado una ruta complicada para lograr algo que debería haber sido sencillo?
También podría comprimir la cola, como la carcasa de un subnodo individual. – leppie