diff --git a/SystemExtensions/Collections/SkipList.cs b/SystemExtensions/Collections/SkipList.cs
new file mode 100644
index 0000000..aa970e0
--- /dev/null
+++ b/SystemExtensions/Collections/SkipList.cs
@@ -0,0 +1,241 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SystemExtensions.Collections
+{
+ ///
+ /// Skip list implementation.
+ ///
+ /// Provided type.
+ public class SkipList : ICollection where T : IComparable
+ {
+ #region Fields
+ private class NodeSet
+ {
+ public TKey Key;
+ public int Level;
+ public NodeSet[] Next;
+
+ public NodeSet(TKey key, int level)
+ {
+ this.Key = key;
+ this.Level = level;
+ Next = new NodeSet[level + 1];
+ }
+ }
+ private int count;
+ private Random random;
+ private NodeSet head;
+ private NodeSet end;
+ private int maxLevel = 10;
+ private int level;
+ #endregion
+ #region Properties
+ ///
+ /// Number of elements in the list.
+ ///
+ public int Count { get => count; }
+ ///
+ /// Specifies if the collection can be modified.
+ ///
+ public bool IsReadOnly { get; set; }
+ #endregion
+ #region Constructors
+ ///
+ /// Creates a new instance of SkipList collection.
+ ///
+ /// Maximum level of the skip list.
+ public SkipList(int maxLevel = 10)
+ {
+ this.maxLevel = maxLevel;
+ random = new Random();
+ head = new NodeSet(default(T), maxLevel);
+ end = head;
+ for(int i = 0; i <= maxLevel; i++)
+ {
+ head.Next[i] = end;
+ }
+ }
+
+ #endregion
+ #region Public Methods
+ ///
+ /// Adds an item to the collection.
+ ///
+ /// Item to be added.
+ public void Add(T item)
+ {
+ NodeSet curNode = head;
+ int newLevel = 0;
+ while (random.Next(0, 2) > 0 && newLevel < maxLevel)
+ {
+ newLevel++;
+ }
+ if (newLevel > level)
+ {
+ level = newLevel;
+ }
+ NodeSet newNode = new NodeSet(item, newLevel);
+ for (var i = 0; i <= newLevel; i++)
+ {
+ if(i > curNode.Level)
+ {
+ curNode = head;
+ }
+ while (curNode.Next[i] != end && curNode.Next[i].Key.CompareTo(item) < 0)
+ {
+ curNode = curNode.Next[i];
+ }
+ newNode.Next[i] = curNode.Next[i];
+ curNode.Next[i] = newNode;
+ }
+ count++;
+ }
+ ///
+ /// Removes provided item from the collection.
+ ///
+ /// Item to be removed.
+ /// True if removal was successful.
+ public bool Remove(T item)
+ {
+ bool removed = false;
+ NodeSet curNode = head;
+ for (var i = 0; i <= maxLevel; i++)
+ {
+ if(i > curNode.Level)
+ {
+ curNode = head;
+ }
+ while (curNode.Next[i] != end && curNode.Next[i].Key.CompareTo(item) < 0)
+ {
+ curNode = curNode.Next[i];
+ }
+ if (curNode.Next[i].Key.CompareTo(item) == 0) //Item is present on this level
+ {
+ curNode.Next[i] = curNode.Next[i].Next[i];
+ removed = true;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (removed)
+ {
+ count--;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ ///
+ /// Clears the collection.
+ ///
+ public void Clear()
+ {
+ for(int i = 0; i < maxLevel; i++)
+ {
+ head.Next[i] = end;
+ }
+ count = 0;
+ }
+ ///
+ /// Checks if item is present in the collection.
+ ///
+ /// Item to be checked.
+ /// True if item is present in the collection.
+ public bool Contains(T item)
+ {
+ if(Find(item) != null)
+ {
+ return true;
+ }
+ return false;
+ }
+ ///
+ /// Copies the skip list contents onto the provided array.
+ ///
+ /// Array to hold the values from the list.
+ /// Index to start insertion in the array.
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ NodeSet node = head.Next[0];
+ while(node != end)
+ {
+ array[arrayIndex] = node.Key;
+ arrayIndex++;
+ node = node.Next[0];
+ }
+ }
+ ///
+ /// Copies the elements from the collection into an array.
+ ///
+ /// Array filled with elements from the collection.
+ public T[] ToArray()
+ {
+ T[] array = new T[count];
+ int index = 0;
+ NodeSet curNode = head.Next[0];
+ while(curNode != end)
+ {
+ array[index] = curNode.Key;
+ index++;
+ curNode = curNode.Next[0];
+ }
+ return array;
+ }
+ ///
+ /// Enumerator that iterates over the collection.
+ ///
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ NodeSet curNode = head.Next[0];
+ while(curNode != end)
+ {
+ yield return curNode.Key;
+ curNode = curNode.Next[0];
+ }
+ }
+ #endregion
+ #region Private Methods
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ throw new NotImplementedException();
+ }
+ private NodeSet Find(T key)
+ {
+ NodeSet curNode = head;
+
+ for(int i = level; i >= 0; i--)
+ {
+ while(curNode.Next[i] != end)
+ {
+ if(curNode.Next[i].Key.CompareTo(key) > 0)
+ {
+ break;
+ }
+ else if(curNode.Next[i].Key.CompareTo(key) == 0)
+ {
+ return curNode.Next[i];
+ }
+ curNode = curNode.Next[i];
+ }
+ }
+
+ curNode = curNode.Next[0];
+ if(curNode != end && curNode.Key.CompareTo(key) == 0)
+ {
+ return curNode;
+ }
+ return null;
+ }
+ #endregion
+ }
+}
diff --git a/SystemExtensions/SystemExtensions.csproj b/SystemExtensions/SystemExtensions.csproj
index 84b461e..45ce300 100644
--- a/SystemExtensions/SystemExtensions.csproj
+++ b/SystemExtensions/SystemExtensions.csproj
@@ -50,6 +50,7 @@
+
diff --git a/SystemExtensionsTests/Collections/SkipListTests.cs b/SystemExtensionsTests/Collections/SkipListTests.cs
new file mode 100644
index 0000000..7c6c427
--- /dev/null
+++ b/SystemExtensionsTests/Collections/SkipListTests.cs
@@ -0,0 +1,128 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using SystemExtensions.Collections;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SystemExtensions.Collections.Tests
+{
+ [TestClass()]
+ public class SkipListTests
+ {
+ SkipList skipList = new SkipList();
+ [TestMethod()]
+ public void SkipListTest()
+ {
+ SkipList skipList = new SkipList();
+ }
+
+ [TestMethod()]
+ public void SkipListTest2()
+ {
+ SkipList skipList = new SkipList(30);
+ }
+
+ [TestMethod()]
+ public void AddTest()
+ {
+ for(int i = 0; i < 200; i++)
+ {
+ skipList.Add(i);
+ }
+ }
+
+ [TestMethod()]
+ public void ClearTest()
+ {
+ for (int i = 0; i < 200; i++)
+ {
+ skipList.Add(i);
+ }
+ skipList.Clear();
+ if(skipList.Count > 0)
+ {
+ Assert.Fail();
+ }
+ }
+
+ [TestMethod()]
+ public void ContainsTest()
+ {
+ for (int i = 0; i < 200; i++)
+ {
+ skipList.Add(i);
+ }
+
+ if (!skipList.Contains(50))
+ {
+ Assert.Fail();
+ }
+ }
+
+ [TestMethod()]
+ public void CopyToTest()
+ {
+ for (int i = 0; i < 200; i++)
+ {
+ skipList.Add(i);
+ }
+ int[] array = new int[skipList.Count];
+ skipList.CopyTo(array, 0);
+ for (int i = 0; i < 200; i++)
+ {
+ if(array[i] != i)
+ {
+ Assert.Fail();
+ }
+ }
+ }
+
+ [TestMethod()]
+ public void ToArrayTest()
+ {
+ for (int i = 0; i < 200; i++)
+ {
+ skipList.Add(i);
+ }
+ int[] array = skipList.ToArray();
+
+ for (int i = 0; i < 200; i++)
+ {
+ if(array[i] != i)
+ {
+ Assert.Fail();
+ }
+ }
+ }
+
+ [TestMethod()]
+ public void GetEnumeratorTest()
+ {
+ for (int i = 0; i < 200; i++)
+ {
+ skipList.Add(i);
+ }
+
+ foreach(int i in skipList)
+ {
+ System.Diagnostics.Debug.WriteLine(i);
+ }
+ }
+
+ [TestMethod()]
+ public void RemoveTest()
+ {
+ for (int i = 0; i < 200; i++)
+ {
+ skipList.Add(i);
+ }
+ skipList.Remove(50);
+ if (skipList.Contains(50))
+ {
+ Assert.Fail();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/SystemExtensionsTests/SystemExtensionsTests.csproj b/SystemExtensionsTests/SystemExtensionsTests.csproj
index 4ba94d6..be24684 100644
--- a/SystemExtensionsTests/SystemExtensionsTests.csproj
+++ b/SystemExtensionsTests/SystemExtensionsTests.csproj
@@ -60,6 +60,7 @@
+