Skip to content

Commit 18de825

Browse files
committed
sortset bug fixed
1 parent 5c7b054 commit 18de825

File tree

5 files changed

+135
-27
lines changed

5 files changed

+135
-27
lines changed

src/CatLib.Core.Tests/Support/SortSet/SortSetTests.cs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
* Document: http://catlib.io/
1010
*/
1111

12+
using Microsoft.VisualStudio.TestTools.UnitTesting;
1213
using System;
1314
using System.Collections.Generic;
14-
using System.Reflection;
15-
using Microsoft.VisualStudio.TestTools.UnitTesting;
1615

1716
namespace CatLib.Tests.Stl
1817
{
@@ -30,6 +29,56 @@ public int Compare(int x, int y)
3029
}
3130
}
3231

32+
[TestMethod]
33+
public void TestRandValue()
34+
{
35+
var sortSets = new SortSet<int, int>();
36+
var random = new Random();
37+
38+
for (var i = 1000; i >= 1; i--)
39+
{
40+
sortSets.Add(i, random.Next(0, 1000));
41+
}
42+
43+
for (var i = 1; i <= 1000; i++)
44+
{
45+
if (sortSets.Remove(i))
46+
{
47+
continue;
48+
}
49+
50+
Assert.Fail("can not remove i : " + i);
51+
}
52+
53+
Assert.AreEqual(0, sortSets.Count);
54+
foreach (var sortSet in sortSets)
55+
{
56+
Assert.Fail();
57+
}
58+
}
59+
60+
[TestMethod]
61+
public void TestRank()
62+
{
63+
var sortSets = new SortSet<int, int>();
64+
65+
sortSets.Add(1000, 85);
66+
sortSets.Add(999, 75);
67+
sortSets.Add(998, 185);
68+
sortSets.Add(997, 85);
69+
sortSets.Add(996, 185);
70+
sortSets.Add(995, 85);
71+
72+
Assert.AreEqual(1, sortSets.GetRank(995));
73+
Assert.AreEqual(995, sortSets.GetElementByRank(1));
74+
Assert.AreEqual(997, sortSets.GetElementByRank(2));
75+
Assert.AreEqual(1000, sortSets.GetElementByRank(3));
76+
Assert.AreEqual(996, sortSets.GetElementByRank(4));
77+
Assert.AreEqual(998, sortSets.GetElementByRank(5));
78+
79+
Assert.AreEqual(3, sortSets.GetRangeCount(80, 90));
80+
}
81+
3382
[TestMethod]
3483
public void TestCustomComparer()
3584
{

src/CatLib.Core.Tests/Support/Util/ReferenceCountTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public void SimpleReferenceCountTest()
7676

7777
var rc = new ReferenceCount(cls);
7878
rc.Retain();
79-
Assert.AreEqual(1, rc.RefCount);
79+
Assert.AreEqual(1, rc.Quote);
8080
rc.Release();
8181

8282
Assert.AreEqual(true, isCall);
@@ -98,7 +98,7 @@ public void TestInheritReferenceCount()
9898
var cls = new TestInherit();
9999

100100
cls.Retain();
101-
Assert.AreEqual(1, cls.RefCount);
101+
Assert.AreEqual(1, cls.Quote);
102102
cls.Release();
103103

104104
Assert.AreEqual(true, cls.IsReleaseCall);

src/CatLib.Core/Support/SortSet/SortSet.cs

Lines changed: 64 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ private class SkipNode
3232
internal struct SkipNodeLevel
3333
{
3434
/// <summary>
35-
/// 前一个结点
35+
/// 下一个结点
3636
/// </summary>
3737
internal SkipNode Forward;
3838

@@ -337,7 +337,7 @@ public TElement[] ToArray()
337337
{
338338
var elements = new TElement[Count];
339339
var node = header.Level[0];
340-
int i = 0;
340+
var i = 0;
341341
while (node.Forward != null)
342342
{
343343
elements[i++] = node.Forward.Element;
@@ -489,19 +489,23 @@ public int GetRangeCount(TScore start, TScore end)
489489
rank += cursor.Level[i].Span;
490490
cursor = cursor.Level[i].Forward;
491491
}
492-
if (bakCursor == null)
492+
493+
if (bakCursor != null)
493494
{
494-
bakCursor = cursor;
495-
bakRank = rank;
495+
continue;
496496
}
497+
498+
bakCursor = cursor;
499+
bakRank = rank;
497500
}
498501

499-
if (!isRight)
502+
if (isRight)
500503
{
501-
cursor = bakCursor;
502-
rank ^= bakRank ^= rank ^= bakRank;
504+
continue;
503505
}
504506

507+
cursor = bakCursor;
508+
rank ^= bakRank ^= rank ^= bakRank;
505509
} while (isRight = !isRight);
506510

507511
return Math.Max(0, rank - bakRank);
@@ -713,7 +717,7 @@ public TElement GetElementByRank(int rank)
713717
{
714718
rank = Math.Max(0, rank);
715719
rank += 1;
716-
int traversed = 0;
720+
var traversed = 0;
717721
var cursor = header;
718722
for (var i = level - 1; i >= 0; i--)
719723
{
@@ -723,15 +727,18 @@ public TElement GetElementByRank(int rank)
723727
traversed += cursor.Level[i].Span;
724728
cursor = cursor.Level[i].Forward;
725729
}
730+
726731
if (traversed == rank)
727732
{
728733
return cursor.Element;
729734
}
730735
}
736+
731737
if (Count > 0)
732738
{
733739
throw new ArgumentOutOfRangeException("Rank is out of range [" + rank + "]");
734740
}
741+
735742
throw new InvalidOperationException("SortSet is Null");
736743
}
737744

@@ -869,9 +876,7 @@ private bool Remove(TElement element, TScore score)
869876
//从跳跃层高到低的进行查找
870877
for (var i = level - 1; i >= 0; --i)
871878
{
872-
while (cursor.Level[i].Forward != null &&
873-
(Compare(cursor.Level[i].Forward.Score, score) <= 0 &&
874-
!cursor.Level[i].Forward.Element.Equals(element)))
879+
while (IsFindNext(cursor.Level[i].Forward, element, score, i))
875880
{
876881
cursor = cursor.Level[i].Forward;
877882
}
@@ -902,27 +907,64 @@ private bool Remove(TElement element, TScore score)
902907
/// <returns>排名,排名以0为底</returns>
903908
private int GetRank(TElement element, TScore score)
904909
{
905-
int rank = 0;
910+
var rank = 0;
906911
var cursor = header;
907912
for (var i = level - 1; i >= 0; --i)
908913
{
909-
while (cursor.Level[i].Forward != null &&
910-
(Compare(cursor.Level[i].Forward.Score, score) <= 0 &&
911-
!cursor.Level[i].Forward.Equals(element)))
914+
while (IsFindNext(cursor.Level[i].Forward, element, score, i))
912915
{
913916
rank += cursor.Level[i].Span;
914917
cursor = cursor.Level[i].Forward;
915918
}
916-
if (cursor != header &&
917-
cursor.Element != null &&
918-
cursor.Element.Equals(element))
919-
{
920-
return rank - 1;
921-
}
922919
}
920+
921+
cursor = cursor.Level[0].Forward;
922+
923+
if (cursor != null && cursor != header &&
924+
cursor.Element != null &&
925+
cursor.Element.Equals(element))
926+
{
927+
return rank;
928+
}
929+
923930
return -1;
924931
}
925932

933+
/// <summary>
934+
/// 是否查询下一个元素
935+
/// </summary>
936+
/// <param name="node">跳跃结点</param>
937+
/// <param name="element">元素</param>
938+
/// <param name="score">分数</param>
939+
/// <param name="level">层级</param>
940+
/// <returns>是否查找下一个</returns>
941+
private bool IsFindNext(SkipNode node, TElement element, TScore score, int level)
942+
{
943+
if (node == null)
944+
{
945+
return false;
946+
}
947+
948+
var compare = Compare(node.Score, score);
949+
if (compare < 0 || compare > 0)
950+
{
951+
return compare < 0;
952+
}
953+
954+
// 如果层级大于0,说明有可能直接定位到元素2,从而导致bug
955+
// 所以我们认为层级大于 0 那么值相等依旧返回前序跳跃结点
956+
//
957+
// ------------------------------------------
958+
// | 元素1(分数:50) | 元素2 (分数:50)
959+
// ------------------------------------------
960+
if (level > 0)
961+
{
962+
return false;
963+
}
964+
965+
return !node.Element.Equals(element);
966+
}
967+
926968
/// <summary>
927969
/// 删除结点关系
928970
/// </summary>

src/CatLib.Core/Support/Util/IReferenceCount.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* Document: http://catlib.io/
1010
*/
1111

12+
using System;
13+
1214
namespace CatLib
1315
{
1416
/// <summary>
@@ -19,6 +21,12 @@ public interface IReferenceCount
1921
/// <summary>
2022
/// 当前引用计数
2123
/// </summary>
24+
int Quote { get; }
25+
26+
/// <summary>
27+
/// 当前引用计数(别名自<see cref="Quote"/>)
28+
/// </summary>
29+
[Obsolete("Please use Quote")]
2230
int RefCount { get; }
2331

2432
/// <summary>

src/CatLib.Core/Support/Util/ReferenceCount.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,23 @@ public class ReferenceCount : IReferenceCount
3232
/// <summary>
3333
/// 当前计数
3434
/// </summary>
35-
public int RefCount
35+
public int Quote
3636
{
3737
get
3838
{
3939
return count;
4040
}
4141
}
4242

43+
/// <summary>
44+
/// 当前计数
45+
/// </summary>
46+
[Obsolete("Please use Quote")]
47+
public int RefCount
48+
{
49+
get { return Quote; }
50+
}
51+
4352
/// <summary>
4453
/// 引用计数
4554
/// </summary>

0 commit comments

Comments
 (0)