//an inner class to actually contain values and the next nodes
class TrieNode<T>
{
private Dictionary<char, TrieNode<T>> _next =
new Dictionary<char, TrieNode<T>>();
public ICollection<T> Values { get; private set; }
public TrieNode()
{
this.Values = new List<T>();
_next = new Dictionary<char, TrieNode<T>>();
}
public void AddValue(string key, int depth, T item)
{
if (depth < key.Length)
{
//keep creating/following nodes until
//we reach the end of the key
TrieNode<T> subNode;
if (!_next.TryGetValue(key[depth], out subNode))
{
subNode = new TrieNode<T>();
_next[key[depth]] = subNode;
}
subNode.AddValue(key, depth + 1, item);
}
else
{
Values.Add(item);
}
}
//get the sub-node for the specific character
public TrieNode<T> GetNext(char c)
{
TrieNode<T> node;
if (_next.TryGetValue(c, out node))
return node;
return null;
}
//get all values in this node, and possibly all nodes under this one
public ICollection<T> GetValues(bool recursive)
{
List<T> values = new List<T>();
values.AddRange(this.Values);
if (recursive)
{
foreach (TrieNode<T> node in _next.Values)
{
values.AddRange(node.GetValues(recursive));
}
}
return values;
}
}
大部分功能都在这个字典树节点里面实现了,但是为了方便起见,我们把一些复杂的东西封装了起来。
class Trie<T>
{
TrieNode<T> _root = new TrieNode<T>();
public void AddValue(string key, T item)
{
_root.AddValue(key, 0, item);
}
public ICollection<T> FindValues(string key, bool recursive)
{
TrieNode<T> next = _root;
int index = 0;
//follow the key to the last node
while (index < key.Length &&
next.GetNext(key[index]) != null)
{
next = next.GetNext(key[index++]);
}
//only get values if we found the entire key
if (index == key.Length)
{
return next.GetValues(recursive);
}
else
{
return new T[0];
}
}
}
作为一个测试程序,示例代码用一系列单词填充了一个字典树并且用一些方式来查询它。你可以在本章的字典树示例代码工程中来查看这些代码。下面是程序的输出:
Non-recursive lookup:
agonize
Recursive lookup:
agonize
agonized
agonizedlies
agonizedly
agonizer
agonizers
agonizes
Non-existent lookup:
Found 0 values