Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update SkipList. Fixed Issues #137, #138, #139, #140 #147

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 82 additions & 59 deletions DataStructures/Lists/SkipList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,6 @@ public class SkipList<T> : ICollection<T>, IEnumerable<T> where T : IComparable<
private readonly int MaxLevel = 32;
private readonly double Probability = 0.5;


/// <summary>
/// Private helper. Used in Add method.
/// </summary>
/// <returns></returns>
private int _getNextLevel()
{
int lvl = 0;

while (_randomizer.NextDouble() < Probability && lvl <= _currentMaxLevel && lvl < MaxLevel)
++lvl;

return lvl;
}


/// <summary>
/// CONSTRUCTOR
/// </summary>
Expand All @@ -53,9 +37,6 @@ public SkipList()
_currentMaxLevel = 1;
_randomizer = new Random();
_firstNode = new SkipListNode<T>(default(T), MaxLevel);

for (int i = 0; i < MaxLevel; ++i)
_firstNode.Forwards[i] = _firstNode;
}


Expand Down Expand Up @@ -94,12 +75,15 @@ public int Level
/// <summary>
/// Access elements by index
/// </summary>
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);
}
}

Expand All @@ -111,47 +95,51 @@ public void Add(T item)
var current = _firstNode;
var toBeUpdated = new SkipListNode<T>[MaxLevel];

// Get nodes for updated
for (int i = _currentMaxLevel - 1; i >= 0; --i)
{
while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item))
while (current.Forwards[i] != null && current.Forwards[i].Value.IsLessThan(item))
{
current = current.Forwards[i];
}

toBeUpdated[i] = current;
}

// Desired position to insert key
current = current.Forwards[0];

// Get the next node level, and update list level if required.
int lvl = _getNextLevel();
if (lvl > _currentMaxLevel)
if(current == null || !current.Value.Equals(item))
{
for (int i = _currentMaxLevel; i < lvl; ++i)
toBeUpdated[i] = _firstNode;

_currentMaxLevel = lvl;
// Get the next node level, and update list level if required.
int lvl = _getNextLevel();
if (lvl > _currentMaxLevel)
{
for (int i = _currentMaxLevel; i < lvl; ++i)
toBeUpdated[i] = _firstNode;

_currentMaxLevel = lvl;
}

var newNode = new SkipListNode<T>(item, lvl);

// Insert the new node into the skip list
for (int i = 0; i < lvl; ++i)
{
newNode.Forwards[i] = toBeUpdated[i].Forwards[i];
toBeUpdated[i].Forwards[i] = newNode;
}

++_count;
}

// New node
var newNode = new SkipListNode<T>(item, lvl);

// Insert the new node into the skip list
for (int i = 0; i < lvl; ++i)
{
newNode.Forwards[i] = toBeUpdated[i].Forwards[i];
toBeUpdated[i].Forwards[i] = newNode;
}

// Increment the count
++_count;
}

/// <summary>
/// Remove element from the list.
/// </summary>
public bool Remove(T item)
{
T deleted;
return Remove(item, out deleted);
return Remove(item, out var _);
}

/// <summary>
Expand All @@ -167,7 +155,7 @@ public bool Remove(T item, out T deleted)
// Mark all nodes as toBeUpdated.
for (int i = _currentMaxLevel - 1; i >= 0; --i)
{
while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item))
while (current.Forwards[i] != null && current.Forwards[i].Value.IsLessThan(item))
current = current.Forwards[i];

toBeUpdated[i] = current;
Expand All @@ -176,7 +164,7 @@ public bool Remove(T item, out T deleted)
current = current.Forwards[0];

// Return default value of T if the item was not found
if (current.Value.IsEqualTo(item) == false)
if (current == null || current.Value.IsEqualTo(item) == false)
{
deleted = default(T);
return false;
Expand All @@ -185,15 +173,21 @@ 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];
{
if (toBeUpdated[i].Forwards[i] != current)
{
break;
}

toBeUpdated[i].Forwards[i] = current.Forwards[i];
}

// Decrement the count
--_count;

// Check to see if we've deleted the highest-level node
// Decrement level
while (_currentMaxLevel > 1 && _firstNode.Forwards[_currentMaxLevel - 1] == _firstNode)
while (_currentMaxLevel > 1 && _firstNode.Forwards[_currentMaxLevel - 1] == null)
--_currentMaxLevel;

// Assign the deleted output parameter to the node.Value
Expand All @@ -206,32 +200,49 @@ public bool Remove(T item, out T deleted)
/// </summary>
public bool Contains(T item)
{
T itemOut;
return Find(item, out itemOut);
return Find(item, out var _);
}

/// <summary>
/// Look for an element and return it if found
/// </summary>
public bool Find(T item, out T result)
{
result = default(T);

var current = _firstNode;

// If find null element then check first element after first node
if (item == null)
{
current = current.Forwards[0];
return current != null && current.Value == null;
}

// Skip null element (in first postion) if contain
if (!IsEmpty && current.Forwards[0].Value == null)
{
current = current.Forwards[0];
}

// Walk after all the nodes that have values less than the node we are looking for
for (int i = _currentMaxLevel - 1; i >= 0; --i)
while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item))
{
while (current.Forwards[i] != null && current.Forwards[i].Value.IsLessThan(item))
{
current = current.Forwards[i];
}
}

current = current.Forwards[0];

// Return true if we found the element; false otherwise
if (current.Value.IsEqualTo(item))
if (current != null && current.Value.IsEqualTo(item))
{
result = current.Value;
return true;
}

result = default(T);
return false;
}

Expand Down Expand Up @@ -302,7 +313,7 @@ public bool TryPeek(out T result)
public IEnumerator<T> GetEnumerator()
{
var node = _firstNode;
while (node.Forwards[0] != null && node.Forwards[0] != _firstNode)
while (node.Forwards[0] != null && node.Forwards[0] != null)
{
node = node.Forwards[0];
yield return node.Value;
Expand Down Expand Up @@ -361,12 +372,24 @@ public void Clear()
_currentMaxLevel = 1;
_randomizer = new Random();
_firstNode = new SkipListNode<T>(default(T), MaxLevel);

for (int i = 0; i < MaxLevel; ++i)
_firstNode.Forwards[i] = _firstNode;
}
#endregion

/// <summary>
/// Private helper. Used in Add method.
/// </summary>
/// <returns></returns>
private int _getNextLevel()
{
int lvl = 1;

while (_randomizer.NextDouble() < Probability && lvl <= _currentMaxLevel && lvl < MaxLevel)
{
++lvl;
}

return lvl;
}
}

}
20 changes: 3 additions & 17 deletions DataStructures/Lists/SkipListNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ namespace DataStructures.Lists
{
public class SkipListNode<T> : IComparable<SkipListNode<T>> where T : IComparable<T>
{
/// <summary>
/// Instance variables
/// </summary>
private T _value;
private SkipListNode<T>[] _forwards;

/// <summary>
/// CONSTRUCTORS
/// </summary>
Expand All @@ -25,20 +19,12 @@ public SkipListNode(T value, int level)
/// <summary>
/// Get and set node's value
/// </summary>
public virtual T Value
{
get { return this._value; }
private set { this._value = value; }
}
public virtual T Value { get; private set; }

/// <summary>
/// Get and set node's forwards links
/// </summary>
public virtual SkipListNode<T>[] Forwards
{
get { return this._forwards; }
private set { this._forwards = value; }
}
public virtual SkipListNode<T>[] Forwards { get; private set; }

/// <summary>
/// Return level of node.
Expand All @@ -55,7 +41,7 @@ public int CompareTo(SkipListNode<T> other)
{
if (other == null)
return -1;

return this.Value.CompareTo(other.Value);
}
}
Expand Down
Loading