icomparer 实现 class 如何决定数组项的排序顺序?

How does icomparer implementing class decide sorting order on the array items?

IComparer.Compare函数的return值是如何决定排序操作顺序的? return 值在决定排序顺序时的意义是什么? Array.Sort() 的流程是如何发生的?

例如:

int[] ii = new int[3] { 8,1,4};
Array.Sort(ii, new myComp1());

有没有办法理解排序操作的流程。我的意思是如果我想决定一个特定的排序顺序,那么我应该如何写 if-else 条件或 return 值?

    class myComp1 : IComparer<int>
    {
            public int Compare(int x, int y)
            {
                if (x == y)
                    return 1;
                else if (x > y)
                    return -1;
                else
                    return 0;
            }
        }

例如,在下面给出的代码中,我不明白比较器函数的 return 值的意义,无论它是按升序还是按降序或某种随机顺序。 MSDN没有解释的很清楚。

任何帮助。

我也想了解一下:下面代码中的Array.Sort()是不是先比较8和1,再比较1和4,再比较1和8?此执行是否有任何流程,以便作为程序员我可以在编写实际代码之前弄清楚它? 谢谢。

int[] kk = new int[3] { 8,1,4};
Array.Sort(kk, new myComp2());
    class myComp2 : IComparer<int>
    {
            public int Compare(int x, int y)
            {
                int res = 0;
                if (x == y)
                    return 1;
                else if (x > y)
                    return 2;
                else
                    return 3;
                return res;
            }
        }

Array.Sort 或 .NET 中的任何其他 .Sort 变体按升序排序项目。

当你实现你的比较器时,结果的含义很简单:

  • 小于 0: x 小于 y
  • 大于 0:x 大于 y
  • 等于 0: x 等于 y
  • 比较操作必须是可传递的,例如1 ≤ 4 ≤ 8.

集合中项目的比较顺序取决于 sorting algorithm,因此无法保证 Compare 调用的特定顺序。

具有 IComparer<> 是一个很好的抽象,在其他场景中也很有用,而不仅仅是排序。

如果您想要任何特定的项目顺序,您可以定义保留传递性的比较器规则,或者可能不使用 .Sort


更新

作为程序员,你应该思考:

public int Compare(int x, int y)
{
  // OPTION 1
  if (x < y)
    return -1; // X is less than Y, place X before Y - acsending order
  ...

  // OPTION 2   
  if (x < y)
    return 1;  // X is less than Y, place X after Y - descending order
  ...

  return 0; // keep order of X and Y if possible (stable comparison only)
}

更新 2

好的,假设我们有一个这样定义的比较器:

interface IComparer<T>
{
  SortPlacement Compare(T x, T y);
}

其中SortPlacement定义如下:

enum SortPlacement
{
  Try_To_Keep_Same_Order_Of_X_and_Y = 0,
  Place_X_Before_Y_Ascending_Order = -1, // or any negative number
  Place_X_After_Y_Descending_Order = 1, // or any positive number
}

当你实现你的比较器时,你非常清楚:

public SortPlacement Compare(int x, int y)
{
  // OPTION 1
  if (x < y)
    return SortPlacement.Place_X_Before_Y_Ascending_Order;
  ...

  // OPTION 2   
  if (x < y)
    return SortPlacement.Place_X_After_Y_Descending_Order;
  ...

  // OPTION 3
  return SortPlacement.Try_To_Keep_Same_Order_Of_X_and_Y;
}

现在忘记愚蠢的枚举类型并将其替换为整数 - 这是一个简单的约定。

排序算法使用 Compare 方法的 return 值来确定在对两个数字进行排序时,哪个数字应该排在另一个数字之前。

鉴于此签名:public int Compare(int x, int y)

return 值表示:

  • returnValue < 0 : x < y
  • returnValue == 0 : x == y
  • returnValue > 0 : x > y

所以如果方法 returns 0,数字被认为是相等的(并且它们的顺序不会改变)。如果它 returns -1,那么第一个数字应该 第二个数字之前。如果它 returns 1,那么第一个数字应该在 第二个数字 之后。

现在,由于您已经更改了 Compare 方法中的定义,您将获得与通常预期不同的项目顺序,但这就是允许自定义比较器的全部意义所在 - 它留下关于 "which comes first" 的决定给你。

但是,由于 return 值实际上仅被评估为 0less than zerogreater than zero,在您的第二个示例中,因为您总是 return 大于零的值,顺序将是未知的(这将取决于所使用的算法)。我这样说是因为当我用 {1, 5, 3} 测试它时它颠倒了它们,但是当我使用 {1, 5, 3, 4, 8} 时,顺序没有改变。

请注意,由于 comp2 return 中的所有案例的值都大于零,因此可以重写:

public int Compare(int x, int y) { return 1; }

另外,Array.Sort的源代码在网上,如果你想看排序算法的使用,但你似乎更感兴趣什么