/// <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++; } }
/// <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); } } }
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; } } }
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); }
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); } }
/// <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)); }
/// <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); }
/// <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++; } } }
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); }
/// <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); } }
/// <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); } }
/// <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); }
/// <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++; }
/// <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++; }
/// <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); }
public SkipListEnumerator(SkipList list) { this.list = list; this.version = list.version; this.current = list.nillNode; }