How to create a trie in c#
This is my own code, pulled from my answer to How to find a word from arrays of characters? :
public class Trie
{
public struct Letter
{
public const string Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static implicit operator Letter(char c)
{
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;
}
}
}
Take a look at this codeplex project:
https://trienet.codeplex.com/
It is a library containing several different variants of well tested generic c# trie classes including patricia trie and parallel trie.
Trie
– the simple trie, allows only prefix search, like.Where(s => s.StartsWith(searchString))
SuffixTrie
- allows also infix search, like.Where(s => s.Contains(searchString))
PatriciaTrie
– compressed trie, more compact, a bit more efficient during look-up, but a quite slower durig build-up.SuffixPatriciaTrie
– the same asPatriciaTrie
, also enabling infix search.ParallelTrie
– very primitively implemented parallel data structure which allows adding data and retriving results from different threads simultaneusly.
A simple Trie implementation.
http://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/Tries.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace AlgorithmsMadeEasy
{
class Tries
{
TrieNode root;
public void CreateRoot()
{
root = new TrieNode();
}
public void Add(char[] chars)
{
TrieNode tempRoot = root;
int total = chars.Count() - 1;
for (int i = 0; i < chars.Count(); i++)
{
TrieNode newTrie;
if (tempRoot.children.Keys.Contains(chars[i]))
{
tempRoot = tempRoot.children[chars[i]];
}
else
{
newTrie = new TrieNode();
if (total == i)
{
newTrie.endOfWord = true;
}
tempRoot.children.Add(chars[i], newTrie);
tempRoot = newTrie;
}
}
}
public bool FindPrefix(char[] chars)
{
TrieNode tempRoot = root;
for (int i = 0; i < chars.Count(); i++)
{
if (tempRoot.children.Keys.Contains(chars[i]))
{
tempRoot = tempRoot.children[chars[i]];
}
else
{
return false;
}
}
return true;
}
public bool FindWord(char[] chars)
{
TrieNode tempRoot = root;
int total = chars.Count() - 1;
for (int i = 0; i < chars.Count(); i++)
{
if (tempRoot.children.Keys.Contains(chars[i]))
{
tempRoot = tempRoot.children[chars[i]];
if (total == i)
{
if (tempRoot.endOfWord == true)
{
return true;
}
}
}
else
{
return false;
}
}
return false;
}
}
public class TrieNode
{
public Dictionary<char, TrieNode> children = new Dictionary<char, TrieNode>();
public bool endOfWord;
}
}
/*
Calling Code:
Tries t = new Tries();
t.CreateRoot();
t.Add("abc".ToCharArray());
t.Add("abgl".ToCharArray());
t.Add("cdf".ToCharArray());
t.Add("abcd".ToCharArray());
t.Add("lmn".ToCharArray());
bool findPrefix1 = t.FindPrefix("ab".ToCharArray());
bool findPrefix2 = t.FindPrefix("lo".ToCharArray());
bool findWord1 = t.FindWord("lmn".ToCharArray());
bool findWord2 = t.FindWord("ab".ToCharArray());
bool findWord3 = t.FindWord("cdf".ToCharArray());
bool findWord4 = t.FindWord("ghi".ToCharArray());
*/