示例#1
0
        /// <summary>
        /// Adds the specified term into the Radix.
        /// </summary>
        /// <param name="term">The term.</param>
        public void Add(string term)
        {
            if (term == null)
            {
                throw new ArgumentNullException("term");
            }


            RadixNode node = head;

            // Adding control char
            var prefixChars = new List <char>(term)
            {
                new char()
            };

            foreach (char prefixChar in prefixChars)
            {
                var child = node.GetChild(prefixChar);

                if (child == null)
                {
                    child = new RadixNode(prefixChar);
                    node.AddChild(child);
                }

                node = child;
            }
        }
示例#2
0
        /// <summary>
        /// Finds the specified prefix.
        /// </summary>
        /// <param name="prefix">The prefix.</param>
        /// <returns></returns>
        public IEnumerable <string> Find(string prefix)
        {
            if (prefix == null)
            {
                throw new ArgumentNullException("prefix");
            }

            StringBuilder.Clear();

            RadixNode node = head;

            foreach (char prefixChar in prefix)
            {
                var child = node.GetChild(prefixChar);
                node = child;

                if (child == null)
                {
                    return(new string[0]);
                }

                StringBuilder.Append(prefixChar);
            }

            return(node.GetChildsTerms(StringBuilder.ToString()));
        }
示例#3
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);
        }
    }
示例#4
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);
        }
    }
示例#5
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);
    }
示例#6
0
 /// <summary>
 /// Adds the child node into the current RadixNode lookup table.
 /// </summary>
 /// <param name="node">The node.</param>
 public void AddChild(RadixNode node)
 {
     radixNodes.Add(node.Char, node);
 }
示例#7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Radix"/> class.
 /// </summary>
 public Radix()
 {
     head = new RadixNode();
 }
示例#8
0
        /// <summary>
        /// Performs a sort of the specified <c>collection</c> in O(n).
        /// </summary>
        /// <param name="collection"></param>
        /// <param name="noOfBaskets">Indicates how many baskets should be used for partitioning the items in the collection.</param>
        public static void RadixSort(IList <int> collection, int noOfBaskets)
        {
            // Create the queues that will be used for storing the partitioned data:
            var queues = new Queue <RadixNode> [noOfBaskets];

            for (int i = 0; i < noOfBaskets; i++)
            {
                queues[i] = new Queue <RadixNode>();
            }

            // Add all the items in the collection to a queue: (The 1st queue has been chosen arbitrarilly.)
            // Perform validation of input at the same time.
            for (int i = 0; i < collection.Count; i++)
            {
                if (collection[i] < 0)
                {
                    throw new NotImplementedException("Negative numbers are not supported by this Radix sort implementation.");
                }
                string text = collection[i].ToString();
                queues[0].Enqueue(new RadixNode(collection[i]));
            }

            // Remember that all the items are in the first queue.
            int[] itemsInQueue_old = new int[noOfBaskets];
            itemsInQueue_old[0] = collection.Count;

            // Start the iterative part, ...
            bool isContinuing = true;

            while (isContinuing)
            {
                isContinuing = false;
                int[] itemsInQueue_new = new int[noOfBaskets];
                // Go through all the queues:
                for (int i = 0; i < queues.Length; i++)
                {
                    // Process all the items in this queue:
                    // (Bear in mind that additional items may be placed in this queue as it is recycled for this iteration.)
                    for (int j = 0; j < itemsInQueue_old[i]; j++)
                    {
                        RadixNode node   = queues[i].Dequeue();
                        int       basket = node.RemainingValue % noOfBaskets;
                        node.RemainingValue = node.RemainingValue / noOfBaskets;
                        if (node.RemainingValue != 0)
                        {
                            isContinuing = true;
                        }
                        queues[basket].Enqueue(node);
                        itemsInQueue_new[basket]++;
                    }
                }
                itemsInQueue_old = itemsInQueue_new;
            }

            // Return the result:
            int r_i = 0;

            // For each queue in the collection of queues, ...
            for (int i = 0; i < queues.Length; i++)
            {
                // Add the items to the final results.
                while (queues[i].Count > 0)
                {
                    collection[r_i++] = queues[i].Dequeue().OriginalValue;
                }
            }
        }
示例#9
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);
    }
示例#10
0
 public RadixTrie(RadixNode root)
 {
     Root = root;
 }
示例#11
0
 /// <summary>
 /// construct a new tree with it's root
 /// </summary>
 public RadixTrie()
 {
     Root = new RadixNode(null, new byte[0]);
 }