Skip to content

Commit 80694da

Browse files
committed
Fix aalhour#137 and aalhour#139 issues. Update skipList logic
1 parent a9ce311 commit 80694da

File tree

2 files changed

+139
-52
lines changed

2 files changed

+139
-52
lines changed

DataStructures/Lists/SkipList.cs

+38-34
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ public SkipList()
3737
_currentMaxLevel = 1;
3838
_randomizer = new Random();
3939
_firstNode = new SkipListNode<T>(default(T), MaxLevel);
40-
41-
for (int i = 0; i < MaxLevel; ++i)
42-
_firstNode.Forwards[i] = _firstNode;
4340
}
4441

4542

@@ -98,36 +95,43 @@ public void Add(T item)
9895
var current = _firstNode;
9996
var toBeUpdated = new SkipListNode<T>[MaxLevel];
10097

98+
// Get nodes for updated
10199
for (int i = _currentMaxLevel - 1; i >= 0; --i)
102100
{
103-
while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item))
101+
while (current.Forwards[i] != null && current.Forwards[i].Value.IsLessThan(item))
102+
{
104103
current = current.Forwards[i];
104+
}
105105

106106
toBeUpdated[i] = current;
107107
}
108108

109-
// Get the next node level, and update list level if required.
110-
int lvl = _getNextLevel();
111-
if (lvl > _currentMaxLevel)
109+
// Desired position to insert key
110+
current = current.Forwards[0];
111+
112+
if(current == null || !current.Value.Equals(item))
112113
{
113-
for (int i = _currentMaxLevel; i < lvl; ++i)
114-
toBeUpdated[i] = _firstNode;
114+
// Get the next node level, and update list level if required.
115+
int lvl = _getNextLevel();
116+
if (lvl > _currentMaxLevel)
117+
{
118+
for (int i = _currentMaxLevel; i < lvl; ++i)
119+
toBeUpdated[i] = _firstNode;
115120

116-
_currentMaxLevel = lvl;
117-
}
121+
_currentMaxLevel = lvl;
122+
}
118123

119-
// New node
120-
var newNode = new SkipListNode<T>(item, lvl);
124+
var newNode = new SkipListNode<T>(item, lvl);
121125

122-
// Insert the new node into the skip list
123-
for (int i = 0; i < lvl; ++i)
124-
{
125-
newNode.Forwards[i] = toBeUpdated[i].Forwards[i];
126-
toBeUpdated[i].Forwards[i] = newNode;
127-
}
126+
// Insert the new node into the skip list
127+
for (int i = 0; i < lvl; ++i)
128+
{
129+
newNode.Forwards[i] = toBeUpdated[i].Forwards[i];
130+
toBeUpdated[i].Forwards[i] = newNode;
131+
}
128132

129-
// Increment the count
130-
++_count;
133+
++_count;
134+
}
131135
}
132136

133137
/// <summary>
@@ -151,7 +155,7 @@ public bool Remove(T item, out T deleted)
151155
// Mark all nodes as toBeUpdated.
152156
for (int i = _currentMaxLevel - 1; i >= 0; --i)
153157
{
154-
while (current.Forwards[i] != _firstNode && current.Forwards[i].Value.IsLessThan(item))
158+
while (current.Forwards[i] != null && current.Forwards[i].Value.IsLessThan(item))
155159
current = current.Forwards[i];
156160

157161
toBeUpdated[i] = current;
@@ -160,7 +164,7 @@ public bool Remove(T item, out T deleted)
160164
current = current.Forwards[0];
161165

162166
// Return default value of T if the item was not found
163-
if (current.Value.IsEqualTo(item) == false)
167+
if (current == null || current.Value.IsEqualTo(item) == false)
164168
{
165169
deleted = default(T);
166170
return false;
@@ -170,18 +174,20 @@ public bool Remove(T item, out T deleted)
170174
// Unlink it from the levels where it exists.
171175
for (int i = 0; i < _currentMaxLevel; ++i)
172176
{
173-
if (toBeUpdated[i].Forwards[i] == current)
177+
if (toBeUpdated[i].Forwards[i] != current)
174178
{
175-
toBeUpdated[i].Forwards[i] = current.Forwards[i];
179+
break;
176180
}
181+
182+
toBeUpdated[i].Forwards[i] = current.Forwards[i];
177183
}
178184

179185
// Decrement the count
180186
--_count;
181187

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

187193
// Assign the deleted output parameter to the node.Value
@@ -194,8 +200,7 @@ public bool Remove(T item, out T deleted)
194200
/// </summary>
195201
public bool Contains(T item)
196202
{
197-
T itemOut;
198-
return Find(item, out itemOut);
203+
return Find(item, out var _);
199204
}
200205

201206
/// <summary>
@@ -207,13 +212,13 @@ public bool Find(T item, out T result)
207212

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

213218
current = current.Forwards[0];
214219

215220
// Return true if we found the element; false otherwise
216-
if (current.Value.IsEqualTo(item))
221+
if (current != null && current.Value.IsEqualTo(item))
217222
{
218223
result = current.Value;
219224
return true;
@@ -290,7 +295,7 @@ public bool TryPeek(out T result)
290295
public IEnumerator<T> GetEnumerator()
291296
{
292297
var node = _firstNode;
293-
while (node.Forwards[0] != null && node.Forwards[0] != _firstNode)
298+
while (node.Forwards[0] != null && node.Forwards[0] != null)
294299
{
295300
node = node.Forwards[0];
296301
yield return node.Value;
@@ -349,9 +354,6 @@ public void Clear()
349354
_currentMaxLevel = 1;
350355
_randomizer = new Random();
351356
_firstNode = new SkipListNode<T>(default(T), MaxLevel);
352-
353-
for (int i = 0; i < MaxLevel; ++i)
354-
_firstNode.Forwards[i] = _firstNode;
355357
}
356358
#endregion
357359

@@ -364,7 +366,9 @@ private int _getNextLevel()
364366
int lvl = 1;
365367

366368
while (_randomizer.NextDouble() < Probability && lvl <= _currentMaxLevel && lvl < MaxLevel)
369+
{
367370
++lvl;
371+
}
368372

369373
return lvl;
370374
}

UnitTest/DataStructuresTests/SkipListTest.cs

+101-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Collections.Generic;
1+
using System.Runtime.InteropServices.ComTypes;
22
using DataStructures.Lists;
33
using Xunit;
44

@@ -7,51 +7,128 @@ namespace UnitTest.DataStructuresTests
77
public static class SkipListTest
88
{
99
[Fact]
10-
public static void AddOneElement()
10+
public static void Initialization_ListIsEmpty()
1111
{
1212
var skipList = new SkipList<int>();
1313

14+
Assert.True(skipList.Count == 0);
15+
Assert.True(skipList.IsEmpty);
16+
Assert.DoesNotContain(0, skipList);
17+
}
18+
19+
[Fact]
20+
public static void Add_NullElement_ListContainNullElement()
21+
{
22+
var skipList = new SkipList<string>();
23+
24+
skipList.Add(null);
25+
26+
Assert.True(skipList.Count == 1);
27+
Assert.Contains(null, skipList);
28+
}
29+
30+
[Theory]
31+
[InlineData(10)]
32+
[InlineData(-10)]
33+
public static void Add_OneElement_ListContainOneElement(int testValue)
34+
{
35+
var skipList = new SkipList<int>();
36+
37+
skipList.Add(testValue);
38+
39+
Assert.True(skipList.Count == 1);
40+
Assert.Contains(testValue, skipList);
41+
}
42+
43+
[Fact]
44+
public static void Add_OneElementTwice_ListContainOneElement()
45+
{
46+
var skipList = new SkipList<int>();
47+
48+
skipList.Add(10);
1449
skipList.Add(10);
1550

1651
Assert.True(skipList.Count == 1);
1752
Assert.Contains(10, skipList);
1853
}
1954

2055
[Fact]
21-
public static void AddBatchOfElements()
56+
public static void Add_DefaultElement_ListContainOneElement()
2257
{
2358
var skipList = new SkipList<int>();
2459

25-
for (int i = 100; i > 50; --i)
26-
{
27-
skipList.Add(i);
28-
}
60+
skipList.Add(default(int));
2961

30-
Assert.True(skipList.Count == 50);
31-
for (int i = 100; i > 50; --i)
62+
Assert.True(skipList.Count == 1);
63+
Assert.Contains(0, skipList);
64+
}
65+
66+
[Fact]
67+
public static void Add_SomeElements_ListContainTheseElements()
68+
{
69+
var skipList = new SkipList<int>();
70+
skipList.Add(0);
71+
skipList.Add(-1);
72+
skipList.Add(1);
73+
skipList.Add(2);
74+
75+
Assert.True(skipList.Count == 4);
76+
int checkValue = -1;
77+
foreach(var item in skipList)
3278
{
33-
Assert.Contains(i, skipList);
79+
Assert.Equal(checkValue, item);
80+
checkValue++;
3481
}
3582
}
3683

3784
[Fact]
38-
public static void AddThreeElementsRemoveOneElement()
85+
public static void Remove_RemoveOneElement_ListIsEmpty()
3986
{
4087
var skipList = new SkipList<int>();
88+
skipList.Add(-10);
4189

42-
skipList.Add(1);
90+
skipList.Remove(-10);
91+
92+
Assert.True(skipList.Count == 0);
93+
Assert.DoesNotContain(0, skipList);
94+
Assert.DoesNotContain(-10, skipList);
95+
}
96+
97+
[Fact]
98+
public static void Remove_RemoveDefaultElement_DoNoRemoveAndListIsEmptyAndAddingIsWork()
99+
{
100+
var skipList = new SkipList<int>();
101+
102+
Assert.DoesNotContain(0, skipList);
103+
skipList.Remove(default(int));
104+
105+
Assert.True(skipList.Count == 0);
106+
Assert.DoesNotContain(0, skipList);
107+
108+
skipList.Add(10);
109+
Assert.True(skipList.Count == 1);
110+
Assert.Contains(10, skipList);
111+
}
112+
113+
[Fact]
114+
public static void Remove_RemoveSomeElements_ListContainOneElement()
115+
{
116+
var skipList = new SkipList<int>();
117+
skipList.Add(0);
118+
skipList.Add(-1);
43119
skipList.Add(2);
44120
skipList.Add(3);
121+
45122
skipList.Remove(2);
123+
skipList.Remove(-1);
124+
skipList.Remove(3);
46125

47-
Assert.True(skipList.Count == 2);
48-
Assert.Contains(1, skipList);
49-
Assert.Contains(3, skipList);
50-
Assert.DoesNotContain(2, skipList);
126+
Assert.True(skipList.Count == 1);
127+
Assert.Contains(0, skipList);
51128
}
52129

53130
[Fact]
54-
public static void AddAndRemoveBatchOfElements()
131+
public static void AddAndRemove_BatchOfElements_ListIsEmpty()
55132
{
56133
var skipList = new SkipList<int>();
57134

@@ -60,16 +137,22 @@ public static void AddAndRemoveBatchOfElements()
60137
skipList.Add(i);
61138
}
62139

140+
Assert.True(skipList.Count == 50);
141+
for (int i = 100; i > 50; --i)
142+
{
143+
Assert.Contains(i, skipList);
144+
}
145+
63146
for (int i = 100; i > 50; --i)
64147
{
65148
skipList.Remove(i);
66149
}
67150

68-
Assert.True(skipList.Count == 0);
69151
for (int i = 100; i > 50; --i)
70152
{
71153
Assert.DoesNotContain(i, skipList);
72154
}
155+
Assert.True(skipList.Count == 0);
73156
}
74157

75158
[Fact]

0 commit comments

Comments
 (0)