private bool Remove(string key, AlphaTrieNode startingNode)
        {
            if (startingNode.Value != null && startingNode.Value.Key == key)
            {
                startingNode.Value = null;
                return(true);
            }

            if (startingNode.Nodes != null)
            {
                for (int i = 0; i < NodeCount; i++)
                {
                    AlphaTrieNode nextNode = startingNode.Nodes[i];
                    if (nextNode != null)
                    {
                        bool retVal = Remove(key, nextNode);
                        if (retVal == true)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
        // 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 IEnumerable <KeyValueReference <string, T> > Traverse(AlphaTrieNode startingNode)
        {
            if (startingNode.Value != null)
            {
                yield return(startingNode.Value);
            }

            if (startingNode.Nodes != null)
            {
                for (int i = 0; i < NodeCount; i++)
                {
                    AlphaTrieNode nextNode = startingNode.Nodes[i];
                    if (nextNode != null)
                    {
                        foreach (var newNode in this.Traverse(nextNode))
                        {
                            yield return(newNode);
                        }
                    }
                }
            }
        }
 public AlphaTrie()
 {
     rootNode = new AlphaTrieNode();
 }
        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);
                }
            }
        }