diff --git a/DataStructures/Lists/SkipList.cs b/DataStructures/Lists/SkipList.cs index 57822aca..9567b5c6 100644 --- a/DataStructures/Lists/SkipList.cs +++ b/DataStructures/Lists/SkipList.cs @@ -28,22 +28,6 @@ public class SkipList : ICollection, IEnumerable where T : IComparable< private readonly int MaxLevel = 32; private readonly double Probability = 0.5; - - /// - /// Private helper. Used in Add method. - /// - /// - private int _getNextLevel() - { - int lvl = 0; - - while (_randomizer.NextDouble() < Probability && lvl <= _currentMaxLevel && lvl < MaxLevel) - ++lvl; - - return lvl; - } - - /// /// CONSTRUCTOR /// @@ -94,12 +78,15 @@ public int Level /// /// Access elements by index /// - public T this[int index] + public T this[T item] { get { - // TODO: - throw new NotImplementedException(); + return Find(item, out var result) ? result : throw new KeyNotFoundException(); + } + set + { + Add(item); } } @@ -119,8 +106,6 @@ public void Add(T item) toBeUpdated[i] = current; } - current = current.Forwards[0]; - // Get the next node level, and update list level if required. int lvl = _getNextLevel(); if (lvl > _currentMaxLevel) @@ -150,8 +135,7 @@ public void Add(T item) /// public bool Remove(T item) { - T deleted; - return Remove(item, out deleted); + return Remove(item, out var _); } /// @@ -185,8 +169,12 @@ public bool Remove(T item, out T deleted) // We know that the node is in the list. // Unlink it from the levels where it exists. for (int i = 0; i < _currentMaxLevel; ++i) + { if (toBeUpdated[i].Forwards[i] == current) + { toBeUpdated[i].Forwards[i] = current.Forwards[i]; + } + } // Decrement the count --_count; @@ -367,6 +355,19 @@ public void Clear() } #endregion + /// + /// Private helper. Used in Add method. + /// + /// + private int _getNextLevel() + { + int lvl = 1; + + while (_randomizer.NextDouble() < Probability && lvl <= _currentMaxLevel && lvl < MaxLevel) + ++lvl; + + return lvl; + } } } diff --git a/DataStructures/Lists/SkipListNode.cs b/DataStructures/Lists/SkipListNode.cs index 8188c747..b847b821 100644 --- a/DataStructures/Lists/SkipListNode.cs +++ b/DataStructures/Lists/SkipListNode.cs @@ -4,12 +4,6 @@ namespace DataStructures.Lists { public class SkipListNode : IComparable> where T : IComparable { - /// - /// Instance variables - /// - private T _value; - private SkipListNode[] _forwards; - /// /// CONSTRUCTORS /// @@ -25,20 +19,12 @@ public SkipListNode(T value, int level) /// /// Get and set node's value /// - public virtual T Value - { - get { return this._value; } - private set { this._value = value; } - } + public virtual T Value { get; private set; } /// /// Get and set node's forwards links /// - public virtual SkipListNode[] Forwards - { - get { return this._forwards; } - private set { this._forwards = value; } - } + public virtual SkipListNode[] Forwards { get; private set; } /// /// Return level of node. @@ -55,7 +41,7 @@ public int CompareTo(SkipListNode other) { if (other == null) return -1; - + return this.Value.CompareTo(other.Value); } } diff --git a/UnitTest/DataStructuresTests/SkipListTest.cs b/UnitTest/DataStructuresTests/SkipListTest.cs index 97ab6378..8ec79e29 100644 --- a/UnitTest/DataStructuresTests/SkipListTest.cs +++ b/UnitTest/DataStructuresTests/SkipListTest.cs @@ -1,4 +1,5 @@ -using DataStructures.Lists; +using System.Collections.Generic; +using DataStructures.Lists; using Xunit; namespace UnitTest.DataStructuresTests @@ -6,30 +7,86 @@ namespace UnitTest.DataStructuresTests public static class SkipListTest { [Fact] - public static void DoTest() + public static void AddOneElement() { var skipList = new SkipList(); - for (int i = 100; i >= 50; --i) - skipList.Add(i); + skipList.Add(10); - for (int i = 0; i <= 35; ++i) - skipList.Add(i); + Assert.True(skipList.Count == 1); + Assert.Contains(10, skipList); + } - for (int i = -15; i <= 0; ++i) - skipList.Add(i); + [Fact] + public static void AddBatchOfElements() + { + var skipList = new SkipList(); - for (int i = -15; i >= -35; --i) + for (int i = 100; i > 50; --i) + { skipList.Add(i); + } - Assert.True(skipList.Count == 124); + Assert.True(skipList.Count == 50); + for (int i = 100; i > 50; --i) + { + Assert.Contains(i, skipList); + } + } - skipList.Clear(); + [Fact] + public static void AddThreeElementsRemoveOneElement() + { + var skipList = new SkipList(); + + skipList.Add(1); + skipList.Add(2); + skipList.Add(3); + skipList.Remove(2); + + Assert.True(skipList.Count == 2); + Assert.Contains(1, skipList); + Assert.Contains(3, skipList); + Assert.DoesNotContain(2, skipList); + } - for (int i = 100; i >= 0; --i) + [Fact] + public static void AddAndRemoveBatchOfElements() + { + var skipList = new SkipList(); + + for (int i = 100; i > 50; --i) + { skipList.Add(i); + } + + for (int i = 100; i > 50; --i) + { + skipList.Remove(i); + } + + Assert.True(skipList.Count == 0); + for (int i = 100; i > 50; --i) + { + Assert.DoesNotContain(i, skipList); + } + } + + [Fact] + public static void ClearList() + { + var skipList = new SkipList(); + + skipList.Add(1); + skipList.Add(2); + skipList.Add(3); + skipList.Clear(); - Assert.True(skipList.Count == 101); + Assert.True(skipList.Count == 0); + Assert.True(skipList.IsEmpty); + Assert.DoesNotContain(1, skipList); + Assert.DoesNotContain(2, skipList); + Assert.DoesNotContain(3, skipList); } } }