它使用Quicksort 算法,该算法在有效(就地)实施时不稳定。这意味着它不保证相等的值在排序后保留其先前的相对位置。
例如,如果你有一堆点:
Point[] points = new Point[]
{
new Point(0, 1),
new Point(0, 2),
new Point(0, 3),
new Point(1, 1),
new Point(1, 2),
new Point(1, 3)
};
然后您使用此比较器仅按 x 坐标对这些点进行排序:
private int CompareByX(Point a, Point b)
{
return a.X - b.X;
}
它只会保证这些点是按它们的 x 坐标排序的,这意味着你很容易得到一个混淆的顺序(当查看 y 坐标时):
Point(0, 3)
Point(0, 2)
Point(0, 1)
Point(1, 3)
Point(1, 2)
Point(1, 1)
[编辑]
这并不意味着排序算法是不确定的(随机的)。对于相同的输入数据,您将在每次运行时获得相同的输出数据。如果您精确地检查算法,您还可以预测它的实际重组方式,但这是不必要的。只需知道在使用排序例程时会发生这种情况就足够了。
这是一个针对您的问题的工作示例,尝试更改测试数据大小(Main 中的第一行)并观察数组在每次运行时如何重新组织:
class Program
{
static void Main()
{
Point[] points = CreateTestData(1, 4).ToArray();
DisplayItems("Before", points);
Array.Sort(points, CompareByX);
DisplayItems("After", points);
Console.ReadLine();
}
private class Point
{
public int X { get; private set; }
public int Y { get; private set; }
public override string ToString()
{ return string.Format("({0},{1})", X, Y); }
public Point(int x, int y)
{ X = x; Y = y; }
}
private static int CompareByX(Point a, Point b)
{ return a.X - b.X; }
private static IEnumerable<Point> CreateTestData(int maxX, int maxY)
{
for (int x = 0; x <= 1; x++)
for (int y = 0; y <= 4; y++)
yield return new Point(x, y);
}
private static void DisplayItems(string msg, Point[] points)
{
Console.WriteLine(msg);
foreach (Point p in points)
Console.WriteLine(p.ToString());
Console.WriteLine();
}
}
当然,如果你扩展比较器委托以包含 Y 坐标,你就不会有这个问题:
private static int CompareByX(Point a, Point b)
{
if (a.X == b.X)
return a.Y - b.Y;
else
return a.X - b.X;
}