/// <summary> /// Adds a new child to this node. /// </summary> /// <param name="str">Next bit of the full prefix</param> /// <returns>The new node</returns> public CompactPrefixTreeNode AddChild(string str) { var newNode = new CompactPrefixTreeNode(str); Children[str[0]] = newNode; return(newNode); }
/// <summary> /// Recursively finds the node that has the exact prefix that's given. /// </summary> /// <param name="currentNode"></param> /// <param name="prefix"></param> /// <returns>Node with the exact prefix or null if such a node doesn't exist.</returns> private CompactPrefixTreeNode FindNodeRecursive(CompactPrefixTreeNode currentNode, string prefix) { var sharedPrefix = SharedPrefix(prefix, currentNode.Prefix); var uniquePrefix = prefix.Substring(sharedPrefix.Length); var uniquePrefixFromCurrentNode = currentNode.Prefix.Substring(sharedPrefix.Length); // Current node's prefix contains all of the search prefix, so this node and all its children have the prefoix if (string.IsNullOrEmpty(uniquePrefix)) { return(currentNode); } // Current node's prefix and search prefix both differ, so there is no node with the exact prefix we are looking for. if (!string.IsNullOrEmpty(uniquePrefixFromCurrentNode)) { return(null); } char nextChar = uniquePrefix[0]; if (currentNode.Children.ContainsKey(nextChar)) { return(FindNodeRecursive(currentNode.Children[nextChar], uniquePrefix)); } else { return(null); } }
public CompactPrefixTreeNode Split(int indexInPrefix) { var prefixFirstHalf = Prefix.Substring(0, indexInPrefix); var prefixOtherHalf = Prefix.Substring(indexInPrefix); Prefix = prefixFirstHalf; var newNode = new CompactPrefixTreeNode(prefixOtherHalf); newNode.PostingListId = PostingListId; newNode.Children = Children; PostingListId = null; Children = new Dictionary <char, CompactPrefixTreeNode>(); Children[prefixOtherHalf[0]] = newNode; return(newNode); }
/// <summary> /// Given a start node, recursively collects all the full terms and their posting list ids contained in the subtree. /// </summary> /// <param name="currentNode"></param> /// <param name="currentPrefix">Used to reconstruct the full term, so that we know which posting list id is for which term.</param> /// <param name="result">Reference to the list that will contain the result.</param> private void CollectSubtreeEntriesRecursive(CompactPrefixTreeNode currentNode, string currentPrefix, ref List <PrefixResult> result) { if (currentNode.PostingListId.HasValue) { result.Add(new PrefixResult { Term = currentPrefix, PostingListId = currentNode.PostingListId.Value }); } foreach (var node in currentNode.Children.Values) { CollectSubtreeEntriesRecursive(node, currentPrefix + node.Prefix, ref result); } }
/// <summary> /// Recursive function for adding new terms to the tree. /// Steps through the tree according to the next character of the prefix until . /// When the appropriate leaf node is reached, sets its value to postingListId. /// </summary> /// <param name="currentNode"></param> /// <param name="prefix"></param> /// <param name="postingListId">Posting list ID to store in the node</param> private void AddRecursive(CompactPrefixTreeNode currentNode, string prefix, int postingListId) { // We have reached the leaf node since its prefix matches our current prefix if (prefix == currentNode.Prefix) { currentNode.PostingListId = postingListId; return; } var sharedPrefix = SharedPrefix(prefix, currentNode.Prefix); var remainingPrefix = prefix.Substring(sharedPrefix.Length); var remainingPrefixFromCurrentNode = currentNode.Prefix.Substring(sharedPrefix.Length); // The node's prefix contains all of the search prefix, // so we just need to split it into 2 nodes for more granularity. if (string.IsNullOrEmpty(remainingPrefix)) { currentNode.Split(sharedPrefix.Length); currentNode.PostingListId = postingListId; return; } // The node's prefix does not contain all of the search prefix, // so we need to look deeper into the tree. else if (string.IsNullOrEmpty(remainingPrefixFromCurrentNode)) { char nextChar = remainingPrefix[0]; if (currentNode.Children.ContainsKey(nextChar)) { AddRecursive(currentNode.Children[nextChar], remainingPrefix, postingListId); } else { AddRecursive(currentNode.AddChild(remainingPrefix), remainingPrefix, postingListId); } } // The node's prefix and search prefix share the same beginning, but then both have more characters, // so we split the current node and create a new node to contain the last bit. else { currentNode.Split(sharedPrefix.Length); AddRecursive(currentNode.AddChild(remainingPrefix), remainingPrefix, postingListId); } }