什么是.NET中实现特里一个明智的方法是什么?特里、明智、方法、NET

2023-09-04 01:10:17 作者:醜人多作怪。

我在后面一个 线索 的概念。但我得到一个有点糊涂,当谈到实施。

I get the concept behind a trie. But I get a little confused when it comes to implementation.

最简单的方法我能想到构造一个特里类型将有一个特里维持内部词典<焦炭,特里> 。其实我已写了一个这样一来,它的和的,但是......这似乎有点小题大做。我的IM pression是一个线索应该是轻量级的,并具有独立的词典<焦炭,特里> 的的每一个节点的似乎并不非常轻巧我。

The most obvious way I could think to structure a Trie type would be to have a Trie maintain an internal Dictionary<char, Trie>. I have in fact written one this way, and it works, but... this seems like overkill. My impression is that a trie should be lightweight, and having a separate Dictionary<char, Trie> for every node does not seem very lightweight to me.

有没有实现这个结构我就是缺少一个更合适的方式?

Is there a more appropriate way to implement this structure that I'm missing?

更新:OK!根据来自Jon和leppie非常有帮助的投入,这是我想出来的,到目前为止:

UPDATE: OK! Based on the very helpful input from Jon and leppie, this is what I've come up with so far:

(1)我有特里类型,它有一个类型的私人 _nodes 成员 Trie.INodeCollection

(1) I have the Trie type, which has a private _nodes member of type Trie.INodeCollection.

(2) Trie.INodeCollection 接口有如下成员组成:

(2) The Trie.INodeCollection interface has the following members:

interface INodeCollection
{
    bool TryGetNode(char key, out Trie node);
    INodeCollection Add(char key, Trie node);
    IEnumerable<Trie> GetNodes();
}

(3)有此接口的三种实现:

(3) There are three implementations of this interface:

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)当第一次构建了一个特里,它的 _nodes 成员。以第一个调用添加创建一个 SingleNode ,并在随后对添加从那里,根据上述的步骤

(4) When a Trie is first constructed, its _nodes member is null. The first call to Add creates a SingleNode, and subsequent calls to Add go from there, according to the steps described above.

这是否有道理?这感觉就像在这个意义上的改进,它的有点的降低的特里(节点都不再完全成熟词典&LT;焦炭,特里&GT; 对象,直到有了孩子足够数量的)。然而,这也成为显著更加复杂。是不是太令人费解?我是否采取了复杂的路线来实现的东西,应该已经直截了当?

Does this make sense? This feels like an improvement in the sense that it somewhat reduces the "bulkiness" of a Trie (nodes are no longer full-blown Dictionary<char, Trie> objects until they have a sufficient number of children). However, it has also become significantly more complex. Is it too convoluted? Have I taken a complicated route to achieve something that should've been straightforward?

推荐答案

那么,你需要每个节点有一些东西,的有效的工具的IDictionary&LT;焦炭,特里&GT; 。你可以写自己的自定义实现,它改变其内部结构的基础上有多少子节点有:

Well, you need each node to have something which effectively implements IDictionary<char, Trie>. You could write your own custom implementation which varies its internal structure based on how many subnodes it has:

对于单个子节点,只使用一个字符特里 对于一个小数目,使用名单,其中元组LT;焦炭,特里&GT;&GT; 的LinkedList&LT;元组LT;焦炭,特里&GT;&GT ; 对于数量众多,使用词典&LT;焦炭,特里&GT; For a single subnode, use just a char and a Trie For a small number, use a List<Tuple<char, Trie>> or a LinkedList<Tuple<char,Trie>> For a large number, use a Dictionary<char, Trie>

(刚刚看到leppie的答案,这是他谈,我相信那种混合的方法。)

(Having just seen leppie's answer, this is the kind of hybrid approach he talks about, I believe.)