Dan*_*Tao 8 .net implementation dictionary trie data-structures
我得到了一个trie背后的概念.但是在实施方面我有点困惑.
我认为构建Trie
类型最明显的方法是Trie
维护内部Dictionary<char, Trie>
.事实上,我已经用这种方式编写了一个,并且它可以工作,但是......这看起来有点过分了.我的印象是trie应该是轻量级的,并且每个节点都有一个单独的Dictionary<char, Trie>
对我来说似乎不是很轻量级.
有没有更合适的方法来实现我缺少的这种结构?
更新:好的!基于Jon和leppie的非常有用的输入,这是我到目前为止所提出的:
(1)我有Trie
类型,它有一个_nodes
类型的私有成员Trie.INodeCollection
.
(2)Trie.INodeCollection
界面有以下成员:
interface INodeCollection
{
bool TryGetNode(char key, out Trie node);
INodeCollection Add(char key, Trie node);
IEnumerable<Trie> GetNodes();
}
Run Code Online (Sandbox Code Playgroud)
(3)此接口有三种实现方式:
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.
}
Run Code Online (Sandbox Code Playgroud)
(4)Trie
首次构建a时,其_nodes
成员为null
.根据上述步骤,第一次调用Add
创建一个SingleNode
以及随后的调用Add
.
这有意义吗?这感觉就像是一种改进,它在一定程度上减少了Trie
(节点不再是完整的Dictionary<char, Trie>
对象,直到它们有足够数量的子节点)的"庞大" .然而,它也变得更加复杂.它太复杂了吗?我是否采取了一条复杂的路线来实现应该直截了当的事情?
好吧,您需要每个节点都有一些可以有效实现IDictionary<char, Trie>
. 您可以编写自己的自定义实现,该实现根据其具有的子节点数量来改变其内部结构:
char
和 aTrie
List<Tuple<char, Trie>>
或 aLinkedList<Tuple<char,Trie>>
Dictionary<char, Trie>
(刚刚看到leppie的回答,我相信这就是他所说的混合方法。)