示例#1
0
        /// <summary>
        /// Removes the element with the specified key from the SkipList.
        /// </summary>
        /// <param name="key">
        /// The key of the element to remove.
        /// </param>
        public void Remove(object key)
        {
            SkipListNode[] update = new SkipListNode[MaxLevel];
            SkipListNode   curr;

            if (Search(key, out curr, update))
            {
                // Take the forward references that point to the node to be
                // removed and reassign them to the nodes that come after it.
                for (int i = 0; i < listLevel &&
                     update[i].forward[i] == curr; i++)
                {
                    update[i].forward[i] = curr.forward[i];
                }

                curr.Dispose();

                // After removing the node, we may need to lower the current
                // skip list level if the node had the highest level of all of
                // the nodes.
                while (listLevel > 1 && nillNode.forward[listLevel - 1] == nillNode)
                {
                    listLevel--;
                }

                // Keep track of the number of nodes.
                count--;
                // Indicate that the skip list has changed.
                version++;
            }
        }
示例#2
0
        /// <summary>
        /// Gets or sets the element with the specified key. This is the
        /// indexer for the SkipList.
        /// </summary>
        public object this[object key]
        {
            get
            {
                object       val = null;
                SkipListNode curr;

                if (Search(key, out curr))
                {
                    val = curr.entry.Value;
                }

                return(val);
            }
            set
            {
                SkipListNode[] update = new SkipListNode[MaxLevel];
                SkipListNode   curr;

                // If the search key already exists in the skip list.
                if (Search(key, out curr, update))
                {
                    // Replace the current value with the new value.
                    curr.entry.Value = value;
                    // Indicate that the skip list has changed.
                    version++;
                }
                // Else the key doesn't exist in the skip list.
                else
                {
                    // Insert the key and value into the skip list.
                    Insert(key, value, update);
                }
            }
        }
示例#3
0
        public void Add(T value)
        {
            SkipListNode <T>[] updates = this.BuildUpdateList(value);
            SkipListNode <T>   current = updates[0];

            if (current[0] != null && current[0].Value.CompareTo(value) == 0)
            {
                return;
            }

            SkipListNode <T> n = new SkipListNode <T>(value, this.ChooseRandomHeight(this.Height + 1));

            this.Count++;

            if (n.Height > this.Height)
            {
                this.Head.IncrementHeight();
                this.Head[this.Head.Height - 1] = n;
            }

            for (int i = 0; i < n.Height; i++)
            {
                if (i < updates.Length)
                {
                    n[i]          = updates[i][i];
                    updates[i][i] = n;
                }
            }
        }
示例#4
0
        public bool Contains(T value)
        {
            SkipListNode <T> curent = this.Head;

            for (int i = this.Height - 1; i >= 0; i--)
            {
                while (curent[i] != null)
                {
                    if (curent[i].Value.CompareTo(value) == 0)
                    {
                        return(true);
                    }
                    else if (curent[i].Value.CompareTo(value) < 0)
                    {
                        curent = curent[i];
                    }
                    else
                    {
                        break;
                    }
                }
            }

            return(false);
        }
示例#5
0
        public bool Remove(T value)
        {
            SkipListNode <T>[] updates = this.BuildUpdateList(value);
            SkipListNode <T>   current = updates[0][0];

            if (current != null && current.Value.CompareTo(value) == 0)
            {
                this.Count--;

                for (int i = 0; i < this.Head.Height; i++)
                {
                    if (updates[i][i] != current)
                    {
                        break;
                    }
                    else
                    {
                        updates[i][i] = current[i];
                    }
                }

                if (this.Head[this.Height - 1] == null)
                {
                    this.Head.DecrementHeight();
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
示例#6
0
        /// <summary>
        /// Searches for the specified key.
        /// </summary>
        /// <param name="key">
        /// The key to search for.
        /// </param>
        /// <returns>
        /// Returns true if the specified key is in the SkipList.
        /// </returns>
        private bool Search(object key)
        {
            SkipListNode curr;

            SkipListNode[] dummy = new SkipListNode[MaxLevel];

            return(Search(key, out curr, dummy));
        }
示例#7
0
        /// <summary>
        /// Search for the specified key using the IComparable interface
        /// implemented by each key.
        /// </summary>
        /// <param name="key">
        /// The key to search for.
        /// </param>
        /// <param name="curr">
        /// A SkipList node to hold the results of the search.
        /// </param>
        /// <param name="update">
        /// An array of nodes holding references to the places in the SkipList
        /// search in which the search dropped down one level.
        /// </param>
        /// <returns>
        /// Returns true if the specified key is in the SkipList.
        /// </returns>
        /// <remarks>
        /// Assumes each key inserted into the SkipList implements the
        /// IComparable interface.
        ///
        /// If the specified key is in the SkipList, the curr parameter will
        /// reference the node with the key. If the specified key is not in the
        /// SkipList, the curr paramater will either hold the node with the
        /// first key value greater than the specified key or null indicating
        /// that the search reached the end of the SkipList.
        /// </remarks>zx
        private bool SearchWithComparable(object key, out SkipListNode curr,
                                          SkipListNode[] update)
        {
            // Make sure key is comparable.
            if (!(key is IComparable))
            {
                string msg = resManager.GetString("ComparableError");
                throw new ArgumentException(msg);
            }

            bool        found = false;
            IComparable comp;

            // Begin at the start of the skip list.
            curr = nillNode;

            // Work our way down from the top of the skip list to the bottom.
            for (int i = listLevel - 1; i >= 0; i--)
            {
                // Get the comparable interface for the current key.
                comp = (IComparable)curr.forward[i].entry.Key;

                // While we haven't reached the end of the skip list and the
                // current key is less than the search key.
                while (curr.forward[i] != nillNode && comp.CompareTo(key) < 0)
                {
                    // Move forward in the skip list.
                    curr = curr.forward[i];
                    // Get the comparable interface for the current key.
                    comp = (IComparable)curr.forward[i].entry.Key;
                }

                // Keep track of each node where we move down a level. This
                // will be used later to rearrange node references when
                // inserting a new element.
                update[i] = curr;
            }

            // Move ahead in the skip list. If the new key doesn't already
            // exist in the skip list, this should put us at either the end of
            // the skip list or at a node with a key greater than the search key.
            // If the new key already exists in the skip list, this should put
            // us at a node with a key equal to the search key.
            curr = curr.forward[0];

            // Get the comparable interface for the current key.
            comp = (IComparable)curr.entry.Key;

            // If we haven't reached the end of the skip list and the
            // current key is equal to the search key.
            if (curr != nillNode && comp.CompareTo(key) == 0)
            {
                // Indicate that we've found the search key.
                found = true;
            }

            return(found);
        }
示例#8
0
        /// <summary>
        /// Copies the elements of the SkipList to an Array, starting at a
        /// particular Array index.
        /// </summary>
        /// <param name="array">
        /// The one-dimensional Array that is the destination of the elements
        /// copied from SkipList.
        /// </param>
        /// <param name="index">
        /// The zero-based index in array at which copying begins.
        /// </param>
        public void CopyTo(Array array, int index)
        {
            // Make sure array isn't null.
            if (array == null)
            {
                string msg = resManager.GetString("NullArrayCopyTo");
                throw new ArgumentNullException(msg);
            }
            // Make sure index is not negative.
            else if (index < 0)
            {
                string msg = resManager.GetString("BadIndexCopyTo");
                throw new ArgumentOutOfRangeException(msg);
            }
            // Array bounds checking.
            else if (index >= array.Length)
            {
                string msg = resManager.GetString("BadIndexCopyTo");
                throw new ArgumentException(msg);
            }
            // Make sure that the number of elements in the skip list is not
            // greater than the available space from index to the end of the
            // array.
            else if ((array.Length - index) < Count)
            {
                string msg = resManager.GetString("BadIndexCopyTo");
                throw new ArgumentException(msg);
            }
            // Else copy elements from skip list into array.
            else
            {
                // Start at the beginning of the skip list.
                SkipListNode curr = nillNode.forward[0];

                // While we haven't reached the end of the skip list.
                while (curr != nillNode)
                {
                    // Copy current value into array.
                    array.SetValue(curr.entry.Value, index);

                    // Move forward in the skip list and array.
                    curr = curr.forward[0];
                    index++;
                }
            }
        }
示例#9
0
        protected SkipListNode <T>[] BuildUpdateList(T value)
        {
            SkipListNode <T>[] updates = new SkipListNode <T> [this.Height];
            SkipListNode <T>   current = this.Head;

            for (int i = this.Height - 1; i >= 0; i--)
            {
                while (current[i] != null && current[i].Value.CompareTo(value) < 0)
                {
                    current = current[i];
                }

                updates[i] = current;
            }

            return(updates);
        }
示例#10
0
 /// <summary>
 /// Sets the enumerator to its initial position, which is before
 /// the first element in the skip list.
 /// </summary>
 public void Reset()
 {
     // Make sure the skip list hasn't been modified since the
     // enumerator was created.
     if (version == list.version)
     {
         current    = list.nillNode;
         moveResult = true;
     }
     // Else this version of the enumerator doesn't match that of
     // the skip list. The skip list has been modified since the
     // creation of the enumerator.
     else
     {
         string msg = list.resManager.GetString("InvalidEnum");
         throw new InvalidOperationException(msg);
     }
 }
示例#11
0
        /// <summary>
        /// Adds an element with the provided key and value to the SkipList.
        /// </summary>
        /// <param name="key">
        /// The Object to use as the key of the element to add.
        /// </param>
        /// <param name="value">
        /// The Object to use as the value of the element to add.
        /// </param>
        public void Add(object key, object value)
        {
            SkipListNode[] update = new SkipListNode[MaxLevel];

            // If key does not already exist in the skip list.
            if (!Search(key, update))
            {
                // Inseart key/value pair into the skip list.
                Insert(key, value, update);
            }
            // Else throw an exception. The IDictionary Add method throws an
            // exception if an attempt is made to add a key that already
            // exists in the skip list.
            else
            {
                string msg = resManager.GetString("KeyExistsAdd");
                throw new ArgumentException(msg);
            }
        }
示例#12
0
        /// <summary>
        /// Search for the specified key using a comparer.
        /// </summary>
        /// <param name="key">
        /// The key to search for.
        /// </param>
        /// <param name="curr">
        /// A SkipList node to hold the results of the search.
        /// </param>
        /// <param name="update">
        /// An array of nodes holding references to the places in the SkipList
        /// search in which the search dropped down one level.
        /// </param>
        /// <returns>
        /// Returns true if the specified key is in the SkipList.
        /// </returns>
        private bool SearchWithComparer(object key, out SkipListNode curr,
                                        SkipListNode[] update)
        {
            bool found = false;

            // Start from the beginning of the skip list.
            curr = nillNode;

            // Work our way down from the top of the skip list to the bottom.
            for (int i = listLevel - 1; i >= 0; i--)
            {
                // While we haven't reached the end of the skip list and the
                // current key is less than the new key.
                while (curr.forward[i] != nillNode &&
                       comparer.Compare(curr.forward[i].entry.Key, key) < 0)
                {
                    // Move forward in the skip list.
                    curr = curr.forward[i];
                }

                // Keep track of each node where we move down a level. This
                // will be used later to rearrange node references when
                // inserting a new element.
                update[i] = curr;
            }

            // Move ahead in the skip list. If the new key doesn't already
            // exist in the skip list, this should put us at either the end of
            // the skip list or at a node with a key greater than the sarch key.
            // If the new key already exists in the skip list, this should put
            // us at a node with a key equal to the search key.
            curr = curr.forward[0];

            // If we haven't reached the end of the skip list and the
            // current key is equal to the search key.
            if (curr != nillNode && comparer.Compare(key, curr.entry.Key) == 0)
            {
                // Indicate that we've found the search key.
                found = true;
            }

            return(found);
        }
示例#13
0
        /// <summary>
        /// Inserts a key/value pair into the SkipList.
        /// </summary>
        /// <param name="key">
        /// The key to insert into the SkipList.
        /// </param>
        /// <param name="val">
        /// The value to insert into the SkipList.
        /// </param>
        /// <param name="update">
        /// An array of nodes holding references to places in the SkipList in
        /// which the search for the place to insert the new key/value pair
        /// dropped down one level.
        /// </param>
        private void Insert(object key, object val, SkipListNode[] update)
        {
            // Get the level for the new node.
            int newLevel = GetNewLevel();

            // If the level for the new node is greater than the skip list
            // level.
            if (newLevel > listLevel)
            {
                // Make sure our update references above the current skip list
                // level point to the header.
                for (int i = listLevel; i < newLevel; i++)
                {
                    update[i] = nillNode;
                }

                // The current skip list level is now the new node level.
                listLevel = newLevel;
            }

            // Create the new node.
            SkipListNode newNode = new SkipListNode(newLevel, key, val);

            // Insert the new node into the skip list.
            for (int i = 0; i < newLevel; i++)
            {
                // The new node forward references are initialized to point to
                // our update forward references which point to nodes further
                // along in the skip list.
                newNode.forward[i] = update[i].forward[i];

                // Take our update forward references and point them towards
                // the new node.
                update[i].forward[i] = newNode;
            }

            // Keep track of the number of nodes in the skip list.
            count++;
            // Indicate that the skip list has changed.
            version++;
        }
示例#14
0
        /// <summary>
        /// Removes all elements from the SkipList.
        /// </summary>
        public void Clear()
        {
            // Start at the beginning of the skip list.
            SkipListNode curr = nillNode.forward[0];
            SkipListNode prev;

            // While we haven't reached the end of the skip list.
            while (curr != nillNode)
            {
                // Keep track of the previous node.
                prev = curr;
                // Move forward in the skip list.
                curr = curr.forward[0];
                // Dispose of the previous node.
                prev.Dispose();
            }

            // Initialize skip list and indicate that it has been changed.
            Initialize();
            version++;
        }
示例#15
0
        /// <summary>
        /// Searches for the specified key.
        /// </summary>
        /// <param name="key">
        /// The key to search for.
        /// </param>
        /// <param name="curr">
        /// A SkipList node to hold the results of the search.
        /// </param>
        /// <param name="update">
        /// An array of nodes holding references to the places in the SkipList
        /// search in which the search dropped down one level.
        /// </param>
        /// <returns>
        /// Returns true if the specified key is in the SkipList.
        /// </returns>
        private bool Search(object key, out SkipListNode curr, SkipListNode[] update)
        {
            // Make sure key isn't null.
            if (key == null)
            {
                string msg = resManager.GetString("NullKey");
                throw new ArgumentNullException(msg);
            }

            bool result;

            // Check to see if we will search with a comparer.
            if (comparer != null)
            {
                result = SearchWithComparer(key, out curr, update);
            }
            // Else we're using the IComparable interface.
            else
            {
                result = SearchWithComparable(key, out curr, update);
            }

            return(result);
        }
示例#16
0
 public SkipListEnumerator(SkipList list)
 {
     this.list    = list;
     this.version = list.version;
     this.current = list.nillNode;
 }