Introduction
Trie
is an ordered tree data structure that uses strings as keys. Unlike
Binary Trees, Trie
s do not store keys associated with the node. The
key is actually determined based on the position of the node on the tree. Any descendants
of a node shares a common prefix of the key string associated with that node. Hence, trie
is also called as Prefix Tree
. The word "trie" comes from Retrieval,
and it is pronounced as "try". To read more about Trie
click here.
Since this data structure is a prefix tree, trie
is commonly used in Dictionaries,
Phone Directories and matching algorithms. Trie
is best-suited for phone directory
(any matching application for that matter) because it is very efficient in matching
strings.
So I have decided to implement Trie
myself in C#. I have created three classes:
Node
: Represents a single tree node;
NodeCollection
: Represents the children of a node;
Trie
: Trie implementation to insert and search nodes.
Implementation
Node
: Node
represents a basic tree node. Node
implements both Depth First
and Breadth First algorithms to search its children. It also contains its Parent
node and Children node. Node
has a key and a Value. Key contains the single character
and the value has the actual value of the node. The actual key of the node will
be determined by suffixing the single character to its parent's key. Node
has a
special property called IsTerminal
. This property is set to true if the key
or a value represents a complete string. See the picture below:

NodeCollection
: This class is a simple collection class which implements
the IEnumerable
interface for iteration operations. This class contains an
internal List
<t> class of type
Node
.
NodeCollection
implements the standard list methods such as
Add( )
,
Contains( )
,
Remove( )
etc.
Trie
: This class implements
the Trie
algorithms such as Insert
and Find
methods.
public static Node InsertNode(string name, Node root)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException("Null Key");
int index = 1;
string key;
Node currentNode = root;
while (index <= name.Length)
{
key = name[index - 1].ToString();
Node resultNode = currentNode.Children.GetNodeByKey(key);
if (resultNode == null)
{
Node newNode = new Node(key, name.Substring(0, index));
if (index == name.Length)
newNode.IsTerminal = true;
currentNode.Children.Add(newNode);
currentNode = newNode;
}
else
{
currentNode = resultNode;
}
index++;
}
return root;
}
The Insert
method inserts the string as one character at a time. It starts
with the first character; if the first character doesn't already exist in the root
node it adds a new node with the new character and returns the new node. Otherwise
it returns the node with the fist character for adding remaining characters. It
loops until it adds the entire string. Once it reaches the last character, it marks
that node as a terminal node because this node represents a complete string in the
tree hierarchy.
The Find
methods is implemented by Depth First
search algorithm. The
tree is searched until the complete string is found. Below is the code.
public static bool Find(Node node, string key)
{
if (string.IsNullOrEmpty(key))
return true;
string first = key.Substring(0, 1);
string tail = key.Substring(1);
Node curNode = node.Children.GetNodeByKey(first);
if (curNode != null)
{
return Find(curNode, tail);
}
else
{
return false;
}
}
I've attached the entire source code above. The source code contains the Trie
class
library and a console application to test the Trie
library. The console application
loads a set of names (stored in names.txt in debug folder) in to the tree and provides
options to run Depth First
& Breadth First
algorithm. The application also provides
options for Directory Look-Up and Find
option.
The class library can be further used to develop a web based phone directory. The
data can also be stored on the client (it is too small) and the Trie
can be implemented
in JavaScript.
Happy Coding,
Madhu