/// <summary> /// Performs the actual recursive insertion of the characters in the item into the Trie nodes /// </summary> /// <param name="node"></param> /// <param name="item"></param> /// <param name="index"></param> protected void AddRecursive(TrieNode node, String item, int index) { // If we are at and end of word - mark the node as ending a word if (item.Length == index) { node.EndsWord = true; return; } char firstChar = item[index]; TrieNode childNode = node.AddOrGetNode(firstChar); if (childNode != null) { AddRecursive(childNode, item, index + 1); } }
/// <summary> /// Performs the actual recursive lookup of the characters in the item /// </summary> /// <param name="node">node to search for matches</param> /// <param name="item">string to be looked-up</param> /// <returns>returns </returns> protected TrieNode FindPrefixRecursive(TrieNode node, string item) { if (String.IsNullOrEmpty(item)) { return node; } char firstChar = item[0]; TrieNode childNode = node.GetChildNode(firstChar); // If there is no corresponding node, then we didn't find our item - return null. if (childNode == null) { return null; } else { // we did find our matching node - go to it and continue matching the rest of the string return FindPrefixRecursive(childNode, item.Substring(1)); } }
/// <summary> /// Adds the requested character to the Node subtree children /// If there is already a child representing the character - return it /// </summary> /// <param name="c"></param> /// <returns></returns> public TrieNode AddOrGetNode(char c) { TrieNode newNode; if (_children == null) _children = new Dictionary<char, TrieNode>(); if (!_children.TryGetValue(c, out newNode)) { // children do not contain c, add a TrieNode newNode = new TrieNode(c); _children.Add(c, newNode); } return newNode; }
/// <summary> /// Trie Consructor /// </summary> public Trie() { _rootNode = new TrieNode(' '); }
/// <summary> /// Performs the actual lookup for the all words contained in the subtree. /// </summary> /// <param name="node">root node of a subtree to look for contained words</param> /// <param name="wordBuilder">a StringBuilder to perform fast character appending</param> /// <param name="completionSetCount">maximum number of words to return</param> /// <param name="completions">A list to contain all the words that are found</param> protected void GetCompletionsRecursive(TrieNode node, StringBuilder wordBuilder, int completionSetCount, List<String> completions) { if ((node == null) || (completions.Count >= completionSetCount)) { // no match or we have enough matches to fulfil request - rollback builder and return wordBuilder.Length -= 1; return; } if (node.EndsWord) { // end reached, append the built word into completions list. completions.Add(wordBuilder.ToString()); } IDictionary<char, TrieNode> childNodes = node.Children; if (childNodes != null) { foreach (KeyValuePair<char, TrieNode> pair in childNodes) { char childChar = pair.Value.Character; wordBuilder.Append(childChar); GetCompletionsRecursive(pair.Value, wordBuilder, completionSetCount, completions); } } wordBuilder.Length -= 1; }