private SkipListNode <TKey, TValue>[] FindRightMostNodes(TKey key) { var rightNodes = new SkipListNode <TKey, TValue> [_maxLevelToUse]; // Start at the top list header node var currentNode = _headNodes[_currentLevel]; for (var i = _currentLevel; i >= 0; i--) { while ((currentNode.Right != _tail) && (_comparerToUse.Compare(currentNode.Right.Key, key) < 0)) { currentNode = currentNode.Right; } // Store this node - the new node will be to the right of it. rightNodes[i] = currentNode; // Check if there is a next level, and if there is move down. if (i > 0) { currentNode = currentNode.Down; } } return(rightNodes); }
/// <summary> /// Gets the enumerator. /// </summary> /// <returns>An enumerator for enumerating though the collection.</returns> public IEnumerator <KeyValuePair <TKey, TValue> > GetEnumerator() { // Start at the bottom level and add all the keys to the return array. SkipListNode <TKey, TValue> startNode = _headNodes[0]; while (startNode.Right != _tail) { startNode = startNode.Right; yield return(new KeyValuePair <TKey, TValue>(startNode.Key, startNode.Value)); } }
/// <summary> /// Adds the specified key. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> public void Add(TKey key, TValue value) { var rightNodes = FindRightMostNodes(key); // Check if the item allready exists in the list. If it does, throw an exception - // we will not allow duplicate items here. if ((rightNodes[0].Right != _tail) && (_comparerToUse.Compare(rightNodes[0].Right.Key, key) == 0)) { throw new ArgumentException(Resources.ItemAlreadyInList); } var newLevel = PickRandomLevel(); if (newLevel > _currentLevel) { for (var i = _currentLevel + 1; i <= newLevel; i++) { rightNodes[i] = _headNodes[i]; } _currentLevel = newLevel; } var newNode = new SkipListNode <TKey, TValue>(key, value) { Right = rightNodes[0].Right }; // Insert the item in the first level rightNodes[0].Right = newNode; // And now insert the node in the rest of the levels, making sure // to update the the links for (var i = 1; i <= _currentLevel; i++) { var previousNode = newNode; newNode = new SkipListNode <TKey, TValue>(key, value) { Right = rightNodes[i].Right }; rightNodes[i].Right = newNode; newNode.Down = previousNode; } _itemsCount++; }
/// <summary> /// Initializes a new instance of the <see cref="SkipList<TKey, TValue>"/> class. /// </summary> /// <param name="maxLevel">The max level.</param> /// <param name="probability">The probability.</param> /// <param name="comparer">The comparer.</param> public SkipList(int maxLevel, double probability, IComparer <TKey> comparer) { if (maxLevel < 1) { throw new ArgumentOutOfRangeException("maxLevel", maxLevel, Resources.MaximumLevelBiggerThan0); } if (comparer == null) { throw new ArgumentNullException("comparer"); } if ((probability > 0.9) || (probability < 0.1)) { throw new ArgumentOutOfRangeException("probability", probability, Resources.InvalidProbability); } _comparerToUse = comparer; _maxLevelToUse = maxLevel; _probabilityToUse = probability; // Initialise the skip list to empty nodes, and link the heads and the tails _headNodes = new SkipListNode <TKey, TValue> [maxLevel]; _headNodes[0] = new SkipListNode <TKey, TValue> { Right = _tail }; for (var i = 1; i < maxLevel; i++) { _headNodes[i] = new SkipListNode <TKey, TValue> { Down = _headNodes[i - 1], Right = _tail }; //headNodes[i - 1].Up = headNodes[i]; } }