Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Array.Sort/IComparable有时在第一次调用时不能正确排序_C#_Arrays_Sorting - Fatal编程技术网

C# Array.Sort/IComparable有时在第一次调用时不能正确排序

C# Array.Sort/IComparable有时在第一次调用时不能正确排序,c#,arrays,sorting,C#,Arrays,Sorting,我试图用C来解决问题,直接将我的解决方案以及其他人的解决方案从cpp和Java中翻译出来 我的问题是listName.Sort或Array.SortlistName,…Comparer.Create。。。在第一次传递期间未正确排序输出。我得打两次电话才能把它分类好 在某些情况下,我在调用Array.Sort时在CompareTo内手动设置断点,故意在闭包内添加对列表的引用,这样我可以在值排序时观察它,并在Array.Sort方法返回之前正确排序,然后我看到一些值返回到错误的顺序 我正在使用它进行

我试图用C来解决问题,直接将我的解决方案以及其他人的解决方案从cpp和Java中翻译出来

我的问题是listName.Sort或Array.SortlistName,…Comparer.Create。。。在第一次传递期间未正确排序输出。我得打两次电话才能把它分类好

在某些情况下,我在调用Array.Sort时在CompareTo内手动设置断点,故意在闭包内添加对列表的引用,这样我可以在值排序时观察它,并在Array.Sort方法返回之前正确排序,然后我看到一些值返回到错误的顺序

我正在使用它进行测试,在输出的第10919行有一个不正确的排序结果示例:

Accepted            My Output
10919   457         10919   461
10920   461         10920   457
如您所见,数字461和457应按其模500值的升序排序,分别为461和457。如果我在下面的代码中再次调用sort方法,那么我最终会得到正确的输出

我想我的问题是,为什么会这样?我的实现有什么问题吗?我的实现几乎是接受的Java或cpp代码的1对1翻译。请注意,我还尝试使用LINQ的OrderBy,它会产生不同的结果,但在调用足够多的时间后最终会得到正确的结果

我有以下带有相应IComparable实现的Number类:

class Number : IComparable<Number>
{
    public int Value { get; }
    public int Mod { get; }
    public bool IsOdd { get; }

    public Number(int val, int mod)
    {
        Value = val;
        Mod = mod;
        IsOdd = val % 2 != 0;
    }

    public int CompareTo(Number other)
    {
        var leftVal = Value;
        var leftMod = Mod;
        var rightVal = other.Value;
        var rightMod = other.Mod;

        var leftOdd = IsOdd;
        var rightOdd = other.IsOdd;

        if (leftMod < rightMod) return -1;
        else if (leftMod > rightMod) return 1;
        else
        {
            if (leftOdd && rightOdd)
            {
                return leftVal > rightVal ? -1 : 1;
            }
            else if (!leftOdd && !rightOdd)
            {
                return leftVal > rightVal ? 1 : -1;
            }
            else if (leftOdd)
            {
                return -1;
            }
            else// (rightOdd)
            {
                return 1;
            }
        }
    }
}
编辑2: 下面是测试用例的一部分,其中出现了奇怪的行为。一个具体的重编步骤是,如果您将测试用例更改为只有38项,并从输入中删除11项,那么457和461将正确排序

输入:

39 500
-121
582
163
457
-86
-296
740
220
-867
-333
-773
11
-446
-259
-238
782
461
756
-474
-21
-358
593
548
-962
-411
45
-604
-977
47
-561
-647
926
578
516
382
-508
-781
-322
712
0 0
输出:

39 500
-977
-474
-962
-446
-411
-867
-358
-333
-322
-296
-781
-773
-259
-238
-647
-121
-604
-86
-561
-21
-508
11
516
45
47
548
578
582
593
163
712
220
740
756
782
382
926
457
461
0 0

您成功地检查了布尔测试中的所有案例,但值是否相等除外。排序算法不仅需要知道元素之间的大小,还需要知道元素之间是否相等

  if (leftMod < rightMod)
    return -1;
  else if (leftMod > rightMod)
    return 1;
  else
  {
    if (leftVal == rightVal)
    {
      return 0; // need this so you don't orphan an element when tested against itself
    }
    if (leftOdd && rightOdd)
    {
      return leftVal > rightVal ? -1 : 1;
    }
    else if (!leftOdd && !rightOdd)
    {
      return leftVal > rightVal ? 1 : -1;
    }
    else if (leftOdd)
    {
      return -1;
    }
    else// (rightOdd)
    {
      return 1;
    }
  }

您成功地检查了布尔测试中的所有案例,但值是否相等除外。排序算法不仅需要知道元素之间的大小,还需要知道元素之间是否相等

  if (leftMod < rightMod)
    return -1;
  else if (leftMod > rightMod)
    return 1;
  else
  {
    if (leftVal == rightVal)
    {
      return 0; // need this so you don't orphan an element when tested against itself
    }
    if (leftOdd && rightOdd)
    {
      return leftVal > rightVal ? -1 : 1;
    }
    else if (!leftOdd && !rightOdd)
    {
      return leftVal > rightVal ? 1 : -1;
    }
    else if (leftOdd)
    {
      return -1;
    }
    else// (rightOdd)
    {
      return 1;
    }
  }

根据Mark Benningfield的回答,我想提出一个概念证明,说明为什么在自定义比较器的实现中包含平等性很重要。不仅存在结果不正确的风险,还有永远得不到结果的风险

尝试使用buggy比较器对两个数字2和1进行排序:

class BuggyComparer : IComparer<int>
{
    public int Compare(int x, int y) => x < y ? -1 : 1; // Equality?
}

var source = new int[] { 2, 1 };
var sorted = source.OrderBy(n => n, new BuggyComparer());
Console.WriteLine(String.Join(", ", sorted)); // Infinite loop

程序没有终止,因为排序无法完成。

根据Mark Benningfield的回答,我想提供一个概念证明,说明为什么在自定义比较器的实现中包含相等性很重要。不仅存在结果不正确的风险,还有永远得不到结果的风险

尝试使用buggy比较器对两个数字2和1进行排序:

class BuggyComparer : IComparer<int>
{
    public int Compare(int x, int y) => x < y ? -1 : 1; // Equality?
}

var source = new int[] { 2, 1 };
var sorted = source.OrderBy(n => n, new BuggyComparer());
Console.WriteLine(String.Join(", ", sorted)); // Infinite loop

由于无法完成排序,程序没有终止。

此代码对这两个数字进行了正确排序。我想您正在从文件中读取较大的输入示例?把密码寄出去。是的。我分别将stdin和stdout从输入文件重定向到StringBuilder,以便自动化测试。“我马上就发布。”MarkBenningfield在纸上手动跟踪,排序正确。我遇到的一个奇怪的行为是,如果我通过添加或删除几行来更改测试用例,那么有时它会正确排序。我想您正在从文件中读取较大的输入示例?把密码寄出去。是的。我分别将stdin和stdout从输入文件重定向到StringBuilder,以便自动化测试。“我马上就发布。”MarkBenningfield在纸上手动跟踪,排序正确。我遇到的一个奇怪的行为是,如果我通过添加或删除几行来更改测试用例,那么有时它会正确排序。出于某种原因,这是有效的。数组.Sort是否将元素与自身进行比较?另外,错误测试用例是457和461,它们不相等,并且永远不会进入这个附加条件。至少对于样本输入来说,这是如何解决问题的?根据算法的不同,排序例程将元素与自身进行比较并不少见。记住,一个非平凡的排序例程会将元素移动很多次。出于某种原因,这是有效的。数组.Sort是否将元素与自身进行比较?另外,错误测试用例是457和461,它们不相等,并且永远不会进入这个附加条件。至少对于样本输入来说,这是如何解决问题的?根据算法的不同,排序例程将元素与自身进行比较并不少见。记住,一个非平凡的排序例程会将元素移动很多。