예제 #1
0
        void enum_objects(ArrayList o, RadixNode n)
        {
            if (n.Object != null)
            {
                o.Add(n.Object);
            }

            foreach (RadixNode nc in n.SubNodes)
            {
                enum_objects(o, nc);
            }
        }
예제 #2
0
        /// <summary>
        /// look for a word in the tree begining at the current node
        /// </summary>
        /// <param name="wordPart"></param>
        /// <param name="curNode"></param>
        /// <returns></returns>
        private RadixNode?LookupRec(byte[] word, int pos, RadixNode curNode)
        {
            int matches = MatchingConsecutiveCharacters(word, pos, curNode);

            if ((matches == 0) || (curNode == Root) ||
                ((matches > 0) && (matches < (word.Length - pos)) && (matches >= curNode.Label.Length)))
            {
                RadixNode?ret     = null;
                int       new_pos = pos + matches;
                foreach (RadixNode child in curNode.SubNodes)
                {
                    if (child.Label[0] == word[new_pos])
                    {
                        ret = LookupRec(word, new_pos, child);
                        if (ret != null)
                        {
                            break;
                        }
                    }
                }

                if (ret == null)
                {
                    ret = curNode;
                }

                return(ret);
            }
            else if (matches == curNode.Label.Length)
            {
                return(curNode);
            }
            else
            {
                return(null);
            }
        }
예제 #3
0
        /// <summary>
        /// given a string and a node the number of characters that the string and the node's label have
        /// in common starting from the first character in each is returned
        /// </summary>
        /// <param name="word">a string that is to be compared with the node's label</param>
        /// <param name="curNode">a node</param>
        /// <returns></returns>
        private int MatchingConsecutiveCharacters(byte[] word, int word_pos, RadixNode curNode)
        {
            int matches   = 0;
            int minLength = 0;

            //see which string is smaller and save it's lenght
            //when cycling throught the two strings we won't go any further than that
            if (curNode.Label.Length >= (word.Length - word_pos))
            {
                minLength = word.Length - word_pos;
            }
            else if (curNode.Label.Length < (word.Length - word_pos))
            {
                minLength = curNode.Label.Length;
            }

            if (minLength > 0)
            {
                //go throught the two streams
                for (int i = 0; i < minLength; i++)
                {
                    //if two characters at the same position have the same value we have one more match
                    if (word[i + word_pos] == curNode.Label[i])
                    {
                        matches++;
                    }
                    else
                    {
                        //if at any position the two strings have different characters break the cycle
                        break;
                    }
                }
            }
            //and return the current number of matches
            return(matches);
        }
예제 #4
0
        /// <summary>
        /// recursively traverse the tree
        /// carry the word you want inserted until a proper place for it is found and it can be inserted there
        /// if a node already stores a substring of the word(substrnig with the same first letter as the word itself)
        /// then that substring must be removed from the word and it's children checked out next
        /// hence the name wordPart - part of a word
        /// </summary>
        /// <param name="wordPart">the part of the word that is to be inserted that is not already included in any of the tree's nodes</param>
        /// <param name="curNode">the node currently traversed</param>
        private RadixNode?InsertRec(byte[] wordPart, RadixNode curNode)
        {
            RadixNode?ret = null;

            //get the number of characters that the word part that is to be inserted and the current node's label have
            //in common starting from the first position of both strings
            //matching characters in the two strings = have the same value at the same position in both strings
            int matches = MatchingConsecutiveCharacters(wordPart, 0, curNode);

            //if we are at the root node
            //OR
            //the number of characters from the two strings that match is
            //bigger than 0
            //smaller than the the part of the word that is to be inserted
            //bigger than the the label of the current node
            if ((matches == 0) || (curNode == Root) ||
                ((matches > 0) && (matches < wordPart.Length) && (matches >= curNode.Label.Length)))
            {
                //remove the current node's label from the word part
                bool   inserted    = false;
                byte[] newWordPart = Util.CopyByte(wordPart, matches);
                //search the node's subnodes and if the subnode label's first character matches
                //the word part's first character then insert the word part after this node(call the
                //current method recursively)
                foreach (RadixNode child in curNode.SubNodes)
                {
                    if (child.Label[0] == newWordPart[0])
                    {
                        inserted = true;
                        ret      = InsertRec(newWordPart, child);
                    }
                }
                if (inserted == false)
                {
                    ret = new RadixNode(curNode, newWordPart);
                    curNode.SubNodes.Add(ret);
                    this.Count++;
                }
            }
            else if (matches < wordPart.Length)
            {
                //in this case we have to nodes that we must add to the tree
                //one is the node that has a label extracted from the current node's label without the string of
                //matching characters(common characters)
                //the other is the node that has it's label extracted from the current word part minus the string
                //of matching characters
                byte[] commonRoot          = Util.CopyByte(wordPart, 0, matches);
                byte[] branchPreviousLabel = Util.CopyByte(curNode.Label, matches);
                byte[] branchNewLabel      = Util.CopyByte(wordPart, matches);

                curNode.Label = commonRoot;

                RadixNode newNodePreviousLabel = new RadixNode(curNode, branchPreviousLabel);
                newNodePreviousLabel.Object = curNode.Object;
                newNodePreviousLabel.SubNodes.AddRange(curNode.SubNodes);

                foreach (RadixNode n in curNode.SubNodes)
                {
                    n.Parent = newNodePreviousLabel;
                }

                curNode.SubNodes.Clear();
                curNode.SubNodes.Add(newNodePreviousLabel);
                curNode.Object = null;

                RadixNode newNodeNewLabel = new RadixNode(curNode, branchNewLabel);
                curNode.SubNodes.Add(newNodeNewLabel);
                ret = newNodeNewLabel;
                this.Count++;
            }
            else if (matches == curNode.Label.Length)
            {
                //in this case we don't do anything because the word is already added
            }
            else if (matches > curNode.Label.Length)
            {
                //add the current word part minus the common characters after the current node
                byte[]    newNodeLabel = Util.CopyByte(curNode.Label, curNode.Label.Length, wordPart.Length);
                RadixNode newNode      = new RadixNode(curNode, newNodeLabel);
                curNode.SubNodes.Add(newNode);
                ret = newNode;
                this.Count++;
            }

            return(ret);
        }
예제 #5
0
 public RadixTrie(RadixNode root)
 {
     Root = root;
 }
예제 #6
0
 /// <summary>
 /// construct a new tree with it's root
 /// </summary>
 public RadixTrie()
 {
     Root = new RadixNode(null, new byte[0]);
 }