私はトライの背後にある概念を理解しています。しかし、実装に関しては少し混乱します。
Trie
タイプを構造化するために私が考えることができる最も明白な方法はTrie
、内部を維持することDictionary<char, Trie>
です。私は実際にこのように書いたので、それは機能しますが...これはやり過ぎのようです。私の印象では、トライは軽量である必要があり、ノードごとDictionary<char, Trie>
に個別に設定することは、私にはそれほど軽量ではないように思われます。
私が見逃しているこの構造を実装するためのより適切な方法はありますか?
更新:OK!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();
}
(3)このインターフェースには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>
ただし、それは非常に複雑になっています。複雑すぎませんか?簡単なはずの何かを達成するために複雑なルートをとったことがありますか?