我得到了trie背后的概念。但是在实现方面我有点困惑。
我能想到的最明显的构造Trie
类型的方法是Trie
维护一个 internal Dictionary<char, Trie>
。事实上,我已经以这种方式编写了一个,并且它有效,但是......这似乎有点矫枉过正。我的印象是 trie 应该是轻量级的,并且每个节点Dictionary<char, Trie>
都有一个单独的节点对我来说似乎不是很轻量级。
有没有更合适的方法来实现我所缺少的这种结构?
更新:好的!根据 Jon 和 leppie 的非常有用的意见,这是我迄今为止提出的:
(1) 我有Trie
类型,它有一个私有_nodes
成员 type Trie.INodeCollection
。
(2)Trie.INodeCollection
接口有以下成员:
interface INodeCollection
{
bool TryGetNode(char key, out Trie node);
INodeCollection Add(char key, Trie node);
IEnumerable<Trie> GetNodes();
}
(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.
}
(4) 当 aTrie
被第一次构造时,它的_nodes
成员是null
。根据上述步骤,第一次调用Add
创建一个SingleNode
,随后调用从那里开始。Add
这有意义吗?从某种意义上说,这感觉像是一种改进,它在一定程度上减少了 a 的“体积” (节点在拥有足够数量的子节点之前Trie
不再是成熟的对象)。Dictionary<char, Trie>
然而,它也变得更加复杂。是不是太纠结了?我是否采取了一条复杂的路线来实现本应直截了当的事情?