Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="p"></param>
        /// <param name="key"></param>
        /// <param name="index"></param>
        /// <param name="dist"></param>
        /// <param name="matches"></param>
        internal void NearNeighborsSearch(
            TstDictionaryEntry p,
            string key,
            int index,
            int dist,
            IList matches
            )
        {
            if (p == null || dist < 0)
            {
                return;
            }

            char c = key[index];

            // low child
            if (dist > 0 || c < p.SplitChar)
            {
                NearNeighborsSearch(p.LowChild, key, index, dist, matches);
            }

            // eq child
            if (p.IsKey)
            {
                if (key.Length - index <= dist)
                {
                    matches.Add(new DictionaryEntry(p.Key, p.Value));
                }
            }
            else
            {
                int localIndex = index;
                if (localIndex != key.Length - 1)
                {
                    ++localIndex;
                }
                int localDist = dist;
                if (c != p.SplitChar)
                {
                    --localDist;
                }

                NearNeighborsSearch(
                    p.EqChild,
                    key,
                    localIndex,
                    localDist,
                    matches
                    );
            }

            // highchild
            if (dist > 0 || c > p.SplitChar)
            {
                NearNeighborsSearch(p.HighChild, key, index, dist, matches);
            }
        }
Пример #2
0
 /// <summary>
 /// Create a dictionary with a specified root.
 /// </summary>
 /// <param name="root">Root of the new dictionary</param>
 protected TstDictionary(TstDictionaryEntry root)
 {
     if (root == null)
     {
         throw new ArgumentNullException("root is null");
     }
     this.root    = root;
     this.version = 0;
 }
Пример #3
0
 /// <summary>
 /// Raises the <see cref="TstTraverser.TreeEntry"/> event.
 /// </summary>
 /// <param name="p">tst node added to the tree</param>
 protected virtual void OnTreeEntry(TstDictionaryEntry p)
 {
     if (TreeEntry != null)
     {
         TreeEntry(this,
                   new TstDictionaryEntryEventArgs(p)
                   );
     }
 }
Пример #4
0
 /// <summary>
 /// Raises the <see cref="TstTraverser.HighChild"/> event.
 /// </summary>
 /// <param name="p">high child about to be added to the tree</param>
 protected virtual void OnLowChild(TstDictionaryEntry p)
 {
     if (LowChild != null)
     {
         LowChild(this,
                  new TstDictionaryEntryEventArgs(p)
                  );
     }
 }
Пример #5
0
        /// <summary>
        /// Determines whether the <see cref="TstDictionary"/> contains a specific key.
        /// </summary>
        /// <param name="key">The key to locate in the <see cref="TstDictionary"/>.</param>
        /// <returns>true if the <see cref="TstDictionary"/> contains an element with the specified key; otherwise, false.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="key"/> is a null reference (Nothing in Visual Basic).
        /// </exception>
        /// <remarks>
        /// <para>Complexity: Uses a Ternary Search Tree (tst) to find the key.</para>
        /// <para>The method behaves exactly as <see cref="TstDictionary.Contains"/>.</para>
        /// </remarks>
        public virtual bool ContainsKey(String key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            TstDictionaryEntry de = Find(key);

            return(de != null && de.IsKey);
        }
Пример #6
0
 /// <summary>
 /// Removes all elements from the <see cref="TstDictionary"/>.
 /// </summary>
 /// <exception cref="NotSupportedException">The <see cref="TstDictionary"/> is read-only.</exception>
 public virtual void Clear()
 {
     if (IsReadOnly)
     {
         throw new NotSupportedException("dictionary is read-only");
     }
     // updating version
     ++version;
     root = null;
 }
Пример #7
0
 /// <summary>Constructs an enumerator over <paramref name="tst"/></summary>
 /// <param name="tst">dictionary to enumerate.</param>
 /// <exception cref="ArgumentNullException">tst is null</exception>
 public TstDictionaryEnumerator(TstDictionary tst)
 {
     if (tst == null)
     {
         throw new ArgumentNullException("tst");
     }
     this.version     = tst.Version;
     this.dictionary  = tst;
     this.currentNode = null;
     this.stack       = null;
 }
Пример #8
0
        ///<summary>
        /// Removes the element with the specified key from the <see cref="TstDictionary"/>.
        /// </summary>
        /// <param name="key">The key of the element to remove.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="key"/> is a null reference (Nothing in Visual Basic).
        /// </exception>
        /// <exception cref="ArgumentException"><paramref name="key"/> is an empty string</exception>
        /// <exception cref="NotSupportedException">The <see cref="TstDictionary"/> is read-only.</exception>
        /// <exception cref="NotSupportedException">The <see cref="TstDictionary"/> has a fixed size.</exception>
        public virtual void Remove(String key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key is null");
            }
            if (key.Length == 0)
            {
                throw new ArgumentException("key length cannot be 0");
            }
            if (IsReadOnly)
            {
                throw new NotSupportedException("dictionary is read-only");
            }
            if (IsFixedSize)
            {
                throw new NotSupportedException("dictionary has fixed size");
            }
            // updating version
            ++version;

            TstDictionaryEntry p = Find(key);

            if (p == null)
            {
                return;
            }
            p.IsKey = false;
            p.Key   = null;

            while (!p.IsKey && !p.HasChildren && p.Parent != null)
            {
                if (p.IsLowChild)
                {
                    p.Parent.LowChild = null;
                }
                else if (p.IsHighChild)
                {
                    p.Parent.HighChild = null;
                }
                else
                {
                    p.Parent.EqChild = null;
                }
                p = p.Parent;
            }

            if (!p.IsKey && !p.HasChildren && p == root)
            {
                root = null;
            }
        }
Пример #9
0
 /// <summary>
 /// Construct a tst node.
 /// </summary>
 /// <param name="parent">parent node</param>
 /// <param name="splitChar">split character</param>
 public TstDictionaryEntry(
     TstDictionaryEntry parent,
     char splitChar
     )
 {
     this.isKey     = false;
     this.key       = null;
     this.value     = null;
     this.parent    = parent;
     this.splitChar = splitChar;
     this.lowChild  = null;
     this.eqChild   = null;
     this.highChild = null;
 }
Пример #10
0
        /// <summary>
        /// Gets or sets the value associated with the specified key.
        /// </summary>
        /// <remarks>
        /// [C#] In C#, this property is the indexer for the <see cref="TstDictionary"/> class.
        /// </remarks>
        /// <param name="key">The key whose value to get or set.</param>
        /// <value>
        /// The value associated with the specified key.
        /// If the specified key is not found, attempting to get it returns a null reference
        /// (Nothing in Visual Basic), and attempting to set it creates a new element using the specified key.
        /// </value>
        /// <exception cref="ArgumentNullException"><paramref name="key"/> is a null reference</exception>
        /// <exception cref="ArgumentException">
        /// The property is set and <paramref name="key"/> is an empty string
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// The property is set and the <see cref="TstDictionary"/> is read-only.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// The property is set, <paramref name="key"/> does not exist in the collection,
        /// and the <see cref="TstDictionary"/> has a fixed size.
        /// </exception>
        public virtual Object this[String key]
        {
            get
            {
                if (key == null)
                {
                    throw new ArgumentNullException("key");
                }
                TstDictionaryEntry de = Find(key);
                if (de == null)
                {
                    return(null);
                }
                else
                {
                    return(de.Value);
                }
            }
            set
            {
                if (key == null)
                {
                    throw new ArgumentNullException("key");
                }
                if (key.Length == 0)
                {
                    throw new ArgumentException("key is an empty string");
                }
                if (IsReadOnly)
                {
                    throw new NotSupportedException("read-only dictionary");
                }
                // updating version
                ++version;

                TstDictionaryEntry de = Find(key);
                if (de == null)
                {
                    Add(key, value);
                }
                else
                {
                    if (IsFixedSize)
                    {
                        throw new NotSupportedException("fixed-size dictionary");
                    }
                    de.Value = value;
                }
            }
        }
Пример #11
0
        /// <summary>
        /// Advances the enumerator to the next element of the collection.
        /// </summary>
        /// <returns>
        /// true if the enumerator was successfully advanced to the next element;
        /// false if the enumerator has passed the end of the collection.
        /// </returns>
        public bool MoveNext()
        {
            this.ThrowIfChanged();

            // we are at the beginning
            if (stack == null)
            {
                stack       = new Stack();
                currentNode = null;
                if (dictionary.Root != null)
                {
                    stack.Push(dictionary.Root);
                }
            }
            // we are at the end node, finished
            else if (currentNode == null)
            {
                throw new InvalidOperationException("out of range");
            }

            if (stack.Count == 0)
            {
                currentNode = null;
            }

            while (stack.Count > 0)
            {
                currentNode = (TstDictionaryEntry)stack.Pop();
                if (currentNode.HighChild != null)
                {
                    stack.Push(currentNode.HighChild);
                }
                if (currentNode.EqChild != null)
                {
                    stack.Push(currentNode.EqChild);
                }
                if (currentNode.LowChild != null)
                {
                    stack.Push(currentNode.LowChild);
                }

                if (currentNode.IsKey)
                {
                    break;
                }
            }

            return(currentNode != null);
        }
Пример #12
0
        /// <summary>
        /// Traverses the <paramref name="p"/> sub-tree.
        /// </summary>
        /// <param name="p">node to traverse.</param>
        protected void Traverse(TstDictionaryEntry p)
        {
            if (p == null)
            {
                return;
            }

            OnTreeEntry(p);

            OnLowChild(p.LowChild);
            Traverse(p.LowChild);
            OnEqChild(p.EqChild);
            Traverse(p.EqChild);
            OnHighChild(p.HighChild);
            Traverse(p.HighChild);
        }
Пример #13
0
        /// <summary>
        /// Creates a shallow copy of the entry
        /// </summary>
        /// <returns>entry shallow copy</returns>
        public Object Clone()
        {
            TstDictionaryEntry entry = new TstDictionaryEntry(Parent, SplitChar);

            if (LowChild != null)
            {
                entry.LowChild = LowChild.Clone() as TstDictionaryEntry;
            }
            if (EqChild != null)
            {
                entry.EqChild = EqChild.Clone() as TstDictionaryEntry;
            }
            if (HighChild != null)
            {
                entry.HighChild = HighChild.Clone() as TstDictionaryEntry;
            }
            return(entry);
        }
Пример #14
0
        /// <summary>
        /// Finds the tst node matching the key.
        /// </summary>
        /// <returns>the <see cref="TstDictionaryEntry"/> mathcing the key, null if not found.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="key"/> is null.</exception>
        public virtual TstDictionaryEntry Find(String key)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            int n = key.Length;

            if (n == 0)
            {
                return(null);
            }

            TstDictionaryEntry p = Root;
            int  index           = 0;
            char c;

            while (index < n && p != null)
            {
                c = key[index];
                if (c < p.SplitChar)
                {
                    p = p.LowChild;
                }
                else if (c > p.SplitChar)
                {
                    p = p.HighChild;
                }
                else
                {
                    if (index == n - 1)
                    {
                        return(p);
                    }
                    else
                    {
                        ++index;
                        p = p.EqChild;
                    }
                }
            }
            return(p);
        }
Пример #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="p"></param>
        /// <param name="key"></param>
        /// <param name="index"></param>
        /// <param name="wildChar"></param>
        /// <param name="matches"></param>
        internal void PartialMatchSearch(
            TstDictionaryEntry p,
            string key,
            int index,
            char wildChar,
            IList matches
            )
        {
            if (p == null)
            {
                return;
            }

            char c = key[index];

            if (c == wildChar || c < p.SplitChar)
            {
                PartialMatchSearch(p.LowChild, key, index, wildChar, matches);
            }

            if (c == wildChar || c == p.SplitChar)
            {
                if (index < key.Length - 1)
                {
                    PartialMatchSearch(p.EqChild, key, index + 1, wildChar, matches);
                }
                else if (p.IsKey)
                {
                    matches.Add(new DictionaryEntry(p.Key, p.Value));
                }
            }

            if (c == wildChar || c > p.SplitChar)
            {
                PartialMatchSearch(p.HighChild, key, index, wildChar, matches);
            }
        }
Пример #16
0
        ///<summary>
        /// Adds an element with the specified key and value into the <see cref="TstDictionary"/>.
        ///</summary>
        /// <param name="key">The key of the element to add.</param>
        /// <param name="value">The value of the element to add. The value can be a null reference (Nothing in Visual Basic).</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="key"/> is a null reference (Nothing in Visual Basic).
        /// </exception>
        /// <exception cref="ArgumentException"><paramref name="key"/> is an empty string</exception>
        /// <exception cref="ArgumentException">
        /// An element with the same key already exists in the <see cref="TstDictionary"/>.
        /// </exception>
        /// <exception cref="NotSupportedException">The <see cref="TstDictionary"/> is read-only.</exception>
        /// <exception cref="NotSupportedException">The <see cref="TstDictionary"/> has a fixed size.</exception>
        public virtual void Add(String key, Object value)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key is null");
            }
            if (key.Length == 0)
            {
                throw new ArgumentException("trying to add empty key");
            }
            if (IsReadOnly)
            {
                throw new NotSupportedException("dictionary is read-only");
            }
            if (IsFixedSize)
            {
                throw new NotSupportedException("dictionary has fixed size");
            }
            // updating version
            ++version;

            // creating root node if needed.
            if (Root == null)
            {
                root = new TstDictionaryEntry(null, key[0]);
            }

            // adding key
            TstDictionaryEntry p = Root;
            int  i = 0;
            char c;

            while (i < key.Length)
            {
                c = key[i];
                if (c < p.SplitChar)
                {
                    if (p.LowChild == null)
                    {
                        p.LowChild = new TstDictionaryEntry(p, c);
                    }
                    p = p.LowChild;
                    continue;
                }
                if (c > p.SplitChar)
                {
                    if (p.HighChild == null)
                    {
                        p.HighChild = new TstDictionaryEntry(p, c);
                    }
                    p = p.HighChild;
                    continue;
                }
                else
                {
                    ++i;
                    if (i == key.Length)
                    {
                        if (p.IsKey)
                        {
                            throw new ArgumentException("key already in dictionary");
                        }
                        break;
                    }
                    if (p.EqChild == null)
                    {
                        p.EqChild = new TstDictionaryEntry(p, key[i]);
                    }
                    p = p.EqChild;
                }
            }
            p.IsKey = true;
            p.Key   = key;
            p.Value = value;
        }
Пример #17
0
 /// <summary>Create a <see cref="TstDictionaryEntry"/> event argument.</summary>
 /// <param name="entry">A <see cref="TstDictionaryEntry"/> entry to pass as argument.</param>
 public TstDictionaryEntryEventArgs(TstDictionaryEntry entry)
 {
     this.entry = entry;
 }
Пример #18
0
 ///<summary>
 /// Constructor
 ///</summary>
 /// <remarks>
 /// Construct an empty ternary search tree.
 /// </remarks>
 public TstDictionary()
 {
     root    = null;
     version = 0;
 }