Example #1
0
        /// <summary>
        /// Recursive function that dDetermines whether the tree contains the specified word.
        /// </summary>
        /// <param name="chars">The chars.</param>
        /// <param name="position">The position.</param>
        /// <param name="node">The node.</param>
        /// <returns>
        ///     <c>true</c> if the tree contains the specified word; otherwise, <c>false</c>.
        /// </returns>
        private bool Contains(char[] chars, int position, TernaryTreeNode node)
        {
            if (node == null)
            {
                return(false);
            }
            char currentChar = chars[position];

            if (node.CurrentChar == currentChar)
            {
                if (position + 1 == chars.Length)
                {
                    if (node.CurrentObject != null)
                    {
                        return(true);
                    }
                    return(false);
                }
                return(Contains(chars, position + 1, node.Middle));
            }
            else if (node.CurrentChar < currentChar)
            {
                return(Contains(chars, position, node.Right));
            }
            else
            {
                return(Contains(chars, position, node.Left));
            }
        }
Example #2
0
        public void Delete(string key)
        {
            var current       = root;
            var index         = 0;
            var previousIndex = 0;
            TernaryTreeNode <char, T> previousKey = root;

            while (current != null && index < key.Length)
            {
                if (!current.Value.Equals(default(T)))
                {
                    previousIndex = index;
                    previousKey   = current;
                }

                var comparisonResult = key[index].CompareTo(current.Key);
                if (comparisonResult < 0)
                {
                    current = current.LeftChild;
                }
                else if (comparisonResult > 0)
                {
                    current = current.RightChild;
                }
                else
                {
                    if (index == key.Length - 1)
                    {
                        if (!current.Value.Equals(default(T)))
                        {
                            Size--;
                            if (current.LeftChild == null && current.MiddleChild == null && current.RightChild == null)
                            {
                                if (key[previousIndex].CompareTo(previousKey.Key) < 0)
                                {
                                    previousKey.LeftChild = null;
                                }
                                else if (key[previousIndex].CompareTo(previousKey.Key) > 0)
                                {
                                    previousKey.RightChild = null;
                                }
                                else
                                {
                                    previousKey.MiddleChild = null;
                                }
                            }
                            else
                            {
                                current.Value = default(T);
                            }
                        }
                    }
                    else
                    {
                        current = current.MiddleChild;
                        index++;
                    }
                }
            }
        }
Example #3
0
        private TernaryTreeNode <char, T> Put(string key, T value, int index, TernaryTreeNode <char, T> node)
        {
            if (node == null)
            {
                node = new TernaryTreeNode <char, T>(key[index]);
            }

            var comparisonResult = key[index].CompareTo(node.Key);

            if (comparisonResult < 0)
            {
                node.LeftChild = Put(key, value, index, node.LeftChild);
            }
            else if (comparisonResult > 0)
            {
                node.RightChild = Put(key, value, index, node.RightChild);
            }
            else
            {
                if (index == key.Length - 1)
                {
                    node.Value = value;
                    Size++;
                }
                else
                {
                    node.MiddleChild = Put(key, value, index + 1, node.MiddleChild);
                }
            }

            return(node);
        }
Example #4
0
        /// <summary>
        /// Prepares for search.
        /// </summary>
        public void PrepareForSearch()
        {
            // Initialize the root
            Root = new TernaryTreeNode();

            // Sort the array
            List <string> keys = new List <string>(words.Keys.ToArray <string>());

            keys.Sort(StringComparer.InvariantCultureIgnoreCase);

            // Start filling the tree starting from the middle until all the elements are in.  It should give good balancing
            DichotomicTraversal(keys, 0, words.Count - 1);

            IsPreparedForSearch = true;
        }
Example #5
0
        /// <summary>
        /// Composes the match list.
        /// </summary>
        /// <param name="node">The current node.</param>
        /// <param name="result">The result that contains all the words.</param>
        /// <returns></returns>
        private List <T> ComposeMatchList(TernaryTreeNode node, List <T> result)
        {
            if (node.CurrentObject != null)
            {
                result.Add(node.CurrentObject);
            }
            if (node.Left != null)
            {
                result = ComposeMatchList(node.Left, result);
            }
            if (node.Middle != null)
            {
                result = ComposeMatchList(node.Middle, result);
            }
            if (node.Right != null)
            {
                result = ComposeMatchList(node.Right, result);
            }

            return(result);
        }
Example #6
0
        private IEnumerable <string> GetKeys(TernaryTreeNode <char, T> node)
        {
            if (node == null)
            {
                throw new InvalidOperationException();
            }

            var queue = new Queue <Tuple <TernaryTreeNode <char, T>, StringBuilder> >();

            queue.Enqueue(new Tuple <TernaryTreeNode <char, T>, StringBuilder>(node,
                                                                               new StringBuilder(node.Key.ToString())));
            while (queue.Count > 0)
            {
                var item    = queue.Dequeue();
                var current = item.Item1;
                var key     = item.Item2;
                if (!current.Value.Equals(default(T)))
                {
                    yield return(key.ToString());
                }

                if (current.LeftChild != null)
                {
                    queue.Enqueue(new Tuple <TernaryTreeNode <char, T>, StringBuilder>(current.LeftChild,
                                                                                       new StringBuilder(key.ToString())));
                }

                if (current.MiddleChild != null)
                {
                    queue.Enqueue(new Tuple <TernaryTreeNode <char, T>, StringBuilder>(current.MiddleChild,
                                                                                       new StringBuilder(key.Append(current.MiddleChild.Key).ToString())));
                }

                if (current.RightChild != null)
                {
                    queue.Enqueue(new Tuple <TernaryTreeNode <char, T>, StringBuilder>(current.RightChild,
                                                                                       new StringBuilder(key.ToString())));
                }
            }
        }
Example #7
0
        /// <summary>
        /// Finds the start node for matching.
        /// </summary>
        /// <param name="chars">The array of chars.</param>
        /// <param name="position">The current position.</param>
        /// <param name="node">The current node.</param>
        /// <returns></returns>
        private TernaryTreeNode FindStartNode(char[] chars, int position, TernaryTreeNode node)
        {
            if (position == chars.Length)
            {
                return(node);
            }

            char currentChar = chars[position];

            if (currentChar == node.CurrentChar)
            {
                return(FindStartNode(chars, position + 1, node.Middle));
            }
            else if (node.CurrentChar < currentChar)
            {
                return(FindStartNode(chars, position, node.Right));
            }
            else
            {
                return(FindStartNode(chars, position, node.Left));
            }
        }
Example #8
0
        /// <summary>
        /// Find matches witht the given prefix.
        /// </summary>
        /// <param name="prefix">The prefix.  Can be empty - all words from the tree are returned in this case.</param>
        /// <returns></returns>
        public IList <T> Matches(string prefix)
        {
            if (!IsPreparedForSearch)
            {
                throw new InvalidOperationException("The tree has to be prepared before searching.");
            }

            var result = new List <T>();
            // Step 1 - find the node node
            string prefixNormilized = string.Empty;

            if (!string.IsNullOrEmpty(prefix))
            {
                prefixNormilized = prefix.ToLowerInvariant();
            }
            TernaryTreeNode start = FindStartNode(prefixNormilized.ToCharArray(), 0, Root);

            // Step 2 - get all words starting from the node node
            result = ComposeMatchList(start, result);

            return(result);
        }
Example #9
0
 /// <summary>
 /// Stores the word in the tree.
 /// </summary>
 /// <param name="word">The word.</param>
 /// <param name="chars">The array of characters (must be in lower case).</param>
 /// <param name="position">The position.</param>
 /// <param name="currentChar">The current char.</param>
 /// <param name="node">The node.</param>
 private void StoreWordInTree(string word, char[] chars, int position, char currentChar, TernaryTreeNode node)
 {
     if (node.CurrentChar == 0)
     {
         Debug.Assert(node.Middle == null);
         node.CurrentChar = currentChar;
         node.Middle      = new TernaryTreeNode();
         if (position + 1 == chars.Length)
         {
             Debug.Assert(node.CurrentObject == null);
             node.CurrentObject = words[word];
             return;
         }
         StoreWordInTree(word, chars, position + 1, chars[position + 1], node.Middle);
     }
     else if (node.CurrentChar == currentChar)
     {
         Debug.Assert(node.Middle != null);
         if (position + 1 == chars.Length)
         {
             Debug.Assert(node.CurrentObject == null);
             node.CurrentObject = words[word];
             return;
         }
         StoreWordInTree(word, chars, position + 1, chars[position + 1], node.Middle);
     }
     else if (node.CurrentChar > currentChar)
     {
         if (node.Left == null)
         {
             node.Left = new TernaryTreeNode();
         }
         StoreWordInTree(word, chars, position, chars[position], node.Left);
     }
     else
     {
         if (node.Right == null)
         {
             node.Right = new TernaryTreeNode();
         }
         StoreWordInTree(word, chars, position, chars[position], node.Right);
     }
 }
Example #10
0
 public void Put(string key, T value)
 {
     root = Put(key, value, 0, root);
 }