// Searches the trie for a node starting with the given key. If multiple are found, null will be returned. public IEnumerable <KeyValueReference <string, T> > FindByKeyStart(string _key) { string key = _key.ToLower(); AlphaTrieNode currentNode = rootNode; int level = -1; while (level < key.Length - 1) { level++; // Found the key exactly here, so return it and all of its underlings. if (currentNode.Value != null && currentNode.Value.Key == key) { foreach (var retKV in Traverse(currentNode)) { yield return(retKV); } } int ix; try { ix = AlphaTrieNode.CharToTrieNodeIndex(key[level]); } catch (InvalidOperationException) { yield break; } // Ran into a dead end. if (currentNode.Nodes == null || currentNode.Nodes[ix] == null) { if (currentNode.Value == null) { yield break; } if (currentNode.Value.Key.StartsWith(key)) { yield return(currentNode.Value); } yield break; } currentNode = currentNode.Nodes[ix]; } foreach (var retKV in Traverse(currentNode)) { yield return(retKV); } }
private void Insert(AlphaTrieNode node, KeyValueReference <string, T> insKV, int level) { if (node.Value != null && node.Value.Key == insKV.Key) { throw new InvalidOperationException("Attempted to insert duplicate key into the trie."); } if (node.Nodes == null && node.Value == null) { node.Value = insKV; return; } if (node.Nodes == null && node.Value != null) { node.Nodes = new AlphaTrieNode[NodeCount]; // Only move the current Value if it isn't exactly there. if (node.Value.Key.Length > level) { KeyValueReference <string, T> moveKV = node.Value; node.Value = null; int im = AlphaTrieNode.CharToTrieNodeIndex(moveKV.Key[level]); node.Nodes[im] = new AlphaTrieNode(moveKV); node.Branches++; } // If ours fits perfectly, we know we had to move the old one. if (insKV.Key.Length == level) { node.Value = insKV; return; } int ii = AlphaTrieNode.CharToTrieNodeIndex(insKV.Key[level]); if (node.Nodes[ii] == null) { node.Nodes[ii] = new AlphaTrieNode(insKV); node.Branches++; } else { Insert(node.Nodes[ii], insKV, level + 1); } return; } if (node.Nodes != null) { // If we go exactly here, stick it in the Value. if (insKV.Key.Length == level) { node.Value = insKV; return; } // Otherwise, make new path or follow the old path. int ii = AlphaTrieNode.CharToTrieNodeIndex(insKV.Key[level]); if (node.Nodes[ii] == null) { node.Nodes[ii] = new AlphaTrieNode(insKV); node.Branches++; } else { Insert(node.Nodes[ii], insKV, level + 1); } } }