C# 在实现IComparable时,为什么相同的项不能以相同的顺序放置
我发现,当我为我的一个类实现CompareTo(..)时,机器之间的顺序是不一致的。当两个对象相等时,它们并不总是按相同的顺序排序。我假设使用一些单线程迭代方法进行排序,所以我假设排序是一致的 对于给定的以下类C# 在实现IComparable时,为什么相同的项不能以相同的顺序放置,c#,.net,C#,.net,我发现,当我为我的一个类实现CompareTo(..)时,机器之间的顺序是不一致的。当两个对象相等时,它们并不总是按相同的顺序排序。我假设使用一些单线程迭代方法进行排序,所以我假设排序是一致的 对于给定的以下类 class Property : ICompareable<Property> { public int Value; public int Name; public int CompareTo(Property other) {
class Property : ICompareable<Property>
{
public int Value;
public int Name;
public int CompareTo(Property other)
{
if(this.Value > other.Value)
return 1;
if(this.Value < other.Value)
return -1;
return 0;
}
}
当我执行
List.sort();
然后,当使用索引单步遍历列表时,香蕉和苹果的顺序会根据我在哪台电脑上执行代码而变化。这是为什么?
列表。排序不能提供稳定的排序:
此实现执行不稳定排序;也就是说,如果两个元素相等,它们的顺序可能不会被保留。相反,稳定排序保留相等元素的顺序
如果需要一个稳定的排序,考虑从LINQ中使用<代码> OrderBy <代码>,这是一个稳定的排序。
< P>因为CopReTTO函数只比较了整数(value)轴,不能保证沿着另一个(名称)轴的顺序。< /P>
即使是具有相同实现和相同输入序列的(例如,List.Sort
)也应产生相同的排序输出。因此,鉴于上述不完整的比较功能,结果可能因以下原因而在不同的环境(PC)中有所不同:
排序实现使用不同的或对环境敏感的算法,或李>
项目的初始顺序因环境而异
当且仅当每个环境中的输入序列顺序相同时,稳定排序(例如)将沿不同环境产生一致的输出:稳定排序没有问题1,但仍受问题2的影响
(虽然给定发布的示例代码可以保证输入顺序,但它可能不是“真实”情况,例如项目最初来自无序源。)
我可能会更新compare函数,这样它就定义了所有项属性的总排序,然后所有环境和排序方法中的所有输入序列的结果都是一致的
这种实施的一个例子是:
public int CompareTo(Property other)
{
var valueCmp = this.Value.CompareTo(other.Value);
if (valueCmp == 0) {
// Same Value, order by Name
return this.Name.CompareTo(other.Name);
} else {
// Different Values
return valueCmp;
}
}
一些排序方法保证,在排序后,比较相等的项目将按照排序前的顺序出现,但这种保证通常会带来成本。很少有排序算法可以在一个步骤中将项目从原始位置直接移动到最终位置(而这样做的算法通常速度较慢)。相反,排序算法会将项目移动几次,通常不会跟踪项目的来源。在Anthony Hoare的“快速排序”算法中,一个典型的步骤是选择一些值并移动对象,以便所有比较值小于该值的对象最终都会出现在所有大于该值的项之前的数组元素中。如果忽略正好等于“轴”值的数组元素,则有四类项:
- 小于轴值且在轴值最终位置之前的数组部分中开始的项
- 小于轴值但在轴值最终位置后面的数组部分中开始的项
- 大于轴值但在轴值最终位置之前的数组部分中开始的项
- 大于轴值且在轴值最终位置后面的数组部分中开始的项
当移动元素以分离轴值上方和下方的元素时,第一类和第四类中的项目(即在轴值最终位置的同一侧开始和结束的项目)通常保持其原始顺序,但与在另一侧开始的项目混合,并按相反顺序复制。由于来自每一侧的值混合在一起,系统无法恢复从轴的一侧到另一侧交叉的项目序列,除非它跟踪这些项目。这样的跟踪需要额外的时间和内存,而Sort
选择不花费这些时间和内存
如果给定列表上的两次Sort
运行始终执行相同的步骤序列,则最终顺序应匹配。然而,Sort
的文档并没有指定它执行的步骤的确切顺序,并且可能一台机器的.NET版本与另一台机器的操作略有不同。需要注意的重要一点是,如果您需要“稳定”排序[排序后相等项目的相对顺序保证与排序前的顺序相匹配],您需要使用一种排序方法来保证这种行为,或者在项目中添加一个额外的字段,该字段可以与项目在数组中的初始位置一起预加载,并使您的比较功能在项目相等时检查该字段。此处回答,因为您只比较整数(值)轴,所以不能保证沿另一个(名称)轴排序请在CompareTo()方法的开头放一个Console.WriteLine(this.Value+“-”+other.Value)。由于它是可比较的,所以当存储在容器中时,不在你的对等方之间。事实上,有些东西是可比的,这并不意味着周围容器的任何特征。不要假设任何未在具体中设置的内容。顺便说一下,您的方法相当于返回this.Value.CompareTo(other.Value)代码>
public int CompareTo(Property other)
{
var valueCmp = this.Value.CompareTo(other.Value);
if (valueCmp == 0) {
// Same Value, order by Name
return this.Name.CompareTo(other.Name);
} else {
// Different Values
return valueCmp;
}
}