Does anyone know where I can find an example of how to construct a trie in C#? I'm trying to take a dictionary/list of words and create a trie with it.
Does anyone know where I can find an example of how to construct a trie in C#? I'm trying to take a dictionary/list of words and create a trie with it.
To get instant suggestions from trie data structure, after loading from strings use the below. (faster retrieval)
public class Trie
{
public struct Letter
{
public const string Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static implicit operator Letter(char c)
{
c = c.ToString().ToUpper().ToCharArray().First();
return new Letter() { Index = Chars.IndexOf(c) };
}
public int Index;
public char ToChar()
{
return Chars[Index];
}
public override string ToString()
{
return Chars[Index].ToString();
}
}
public class Node
{
public string Word;
public bool IsTerminal { get { return Word != null; } }
public Dictionary<Letter, Node> Edges = new Dictionary<Letter, Node>();
}
public Node Root = new Node();
public Trie(string[] words)
{
for (int w = 0; w < words.Length; w++)
{
var word = words[w];
var node = Root;
for (int len = 1; len <= word.Length; len++)
{
var letter = word[len - 1];
Node next;
if (!node.Edges.TryGetValue(letter, out next))
{
next = new Node();
if (len == word.Length)
{
next.Word = word;
}
node.Edges.Add(letter, next);
}
node = next;
}
}
}
public List<string> GetSuggestions(string word, int max)
{
List<string> outPut = new List<string>();
var node = Root;
int i = 0;
foreach (var l in word)
{
Node cNode;
if (node.Edges.TryGetValue(l, out cNode))
{
node = cNode;
}
else
{
if (i == word.Length - 1)
return outPut;
}
i++;
}
GetChildWords(node, ref outPut, max);
return outPut;
}
public void GetChildWords(Node n, ref List<string> outWords, int Max)
{
if (n.IsTerminal && outWords.Count < Max)
outWords.Add(n.Word);
foreach (var item in n.Edges)
{
GetChildWords(item.Value, ref outWords, Max);
}
}
}
Simple and beautiful:
class Trie
{
private readonly string _key;
private string _value;
private List<Trie> _path;
private List<Trie> _children;
public Trie(string key = "root", string value = "root_val")
{
this._key = key;
this._value = value;
this._path = this._children = new List<Trie>();
}
public void Initialize(Dictionary<string, string> nodes, int keyLength = 1)
{
foreach (var node in nodes)
{
this.Add(node, keyLength);
}
}
public void Add(KeyValuePair<string, string> node, int keyLength = 1)
{
if (this._children.Count == 0 || !this._children.Any(ch => (node.Key.StartsWith(ch._key)) || (ch._key == node.Key)))
{
//For any item that could be a child of newly added item
Predicate<Trie> possibleChildren = (Trie ch) => { return ch._key.StartsWith(node.Key); };
var newChild = new Trie(node.Key, node.Value);
newChild._children.AddRange(this._children.FindAll(possibleChildren));
this._children.RemoveAll(possibleChildren);
this._children.Add(newChild);
}
else
{
this._children.First(ch => (ch._key == node.Key) || (node.Key.Substring(0, keyLength) == ch._key)).Add(node, keyLength + 1);
}
}
public void Delete(string key, bool recursively = true)
{
var newChildren = new List<Trie>(this._children);
foreach (var child in this._children)
{
if (child._key == key)
{
if (!recursively)
{
newChildren.AddRange(child._children);
}
newChildren.Remove(child);
}
else
{
child.Delete(key, recursively);
}
}
this._children = newChildren;
}
public List<Trie> Find(string key, int keyLength = 1)
{
this._path = new List<Trie>();
if (key.Length >= keyLength - 1 && this._key == key.Substring(0, keyLength - 1))
{
this._path.Add(this);
}
foreach (var child in this._children)
{
var childPath = child.Find(key, keyLength + 1);
this._path.AddRange(childPath);
}
return this._path;
}
}
var items = new Dictionary<string, string>
{
{ "a", "First level item" },
{ "b", "First level item"},
{ "ad", "Second level item"},
{ "bv", "Second level item"},
{ "adf", "Third level item"},
{ "adg", "Third level item"},
{ "bvc", "Third level item"},
{ "bvr", "Third level item"}
};
var myTree = new Trie();
myTree.Initialize(items);