在我当前的项目中,我需要根据它们的位置对节点列表进行排序,该位置由两个浮点值表示。我在Node类中实现了IComparable接口,最初将其用作CompareTo方法:
public int CompareTo(Node other)
{
if(y > other.y)
return 1;
else if(y < other.y)
return -1;
else if(x > other.x)
return 1;
else
return -1;
}
然后我简单地调用了nodeList.Sort()。我们的想法是节点将按其Y排序,如果它们相等,则它们将按其X排序。 当我使用12个节点对其进行测试时,这很有效,但在将节点数增加到21之后,节点的顺序突然出现错误:
x y
0: 2,089 | 0,048
1: 1,195 | 0,145
2: 2,603 | 0,499
3: 1,750 | 0,750
4: 0,478 | 0,526
5: 2,620 | 1,942
6: 2,868 | 1,473
7: 2,806 | 0,960
8: 2,071 | 2,146
9: 1,452 | 2,119
...
我设法通过将CompareTo方法替换为:
来使其正常工作public int CompareTo(Node other)
{
int comparison = y.CompareTo(other.y);
if (comparison != 0)
return comparison;
else
return x.CompareTo(other.x);
}
现在它对包含12个节点的列表和具有21个节点的列表进行了正确排序。
使用它的另一个测试也给出了正确的结果:
public int CompareTo(Node other)
{
int comparison = Math.Sign(y - other.y);
if (comparison != 0)
return comparison;
else
return Math.Sign(x - other.x);
}
我想知道的是为什么在添加更多节点后我的第一次尝试失败了?我做了一些关于浮点值比较的搜索,但是我发现在查看两个浮点数是否相等时可能会出错,这不是这里的情况(或者是吗?)。
我可以想象它与List.Sort()在列表具有> 16个元素时使用不同的算法这一事实有关,但我仍然不明白我的第一次尝试与float不同的原因。的CompareTo()?
答案 0 :(得分:2)
你给出的原始排序函数没有正确处理相等的值,所以a.CompareTo(a)返回-1而不是预期的0.这不是CompareTo()的预期行为,它应该是传递的。 List.Sort()的内部实现可能依赖于此传递性,这将在您的实现中破坏。
如果您有兴趣进一步深入了解List.Sort()的内容,请查看ArraySortHelper的参考源,它由Array.Sort调用,由List调用。分类。看起来该算法依赖于.NET版本,并且还使用动态切换方法的IntroSort。