在List <t> .Sort()方法中,是否与自身进行了比较?</t>

时间:2011-09-10 18:13:18

标签: c# sorting quicksort icomparer

如果我将自定义IComparer传递给List的Sort()方法的实例,是否会使用相同的项调用比较器的Compare(x,y)方法?

即。是否有可能调用Compare(x,x)

修改:对列表项不同的情况更感兴趣。

4 个答案:

答案 0 :(得分:10)

我写了一个测试程序来试试。看起来它实际上 比较()相同的元素与自身相同(至少两次调用同一项的Compare())。在这个程序中,使用参数(2,2)调用Compare()。

using System;
using System.Collections.Generic;

static class Program
{
    class MyComparer : Comparer<int>
    {
        public override int Compare(int x, int y)
        {
            Console.WriteLine("Compare(" + x + ", " + y + ")");
            if (x < y) return -1;
            if (x > y) return 1;
            return 0;
        }
    }

    static void Main()
    {
        MyComparer comparer = new MyComparer();
        List<int> list = new List<int> { 1, 2, 3 };
        list.Sort(comparer);
        return;

    }
}

输出是:

Compare(1, 2)
Compare(1, 3)
Compare(2, 3)
Compare(1, 2)
Compare(2, 2)
Compare(2, 3)
Compare(2, 2)

答案 1 :(得分:8)

来自docs

  

此方法使用Array.Sort,它使用QuickSort算法。

QuickSort绝不会将项目与自身进行比较。 QuickSort的某些实现会将项目与自身进行比较。如果该项目在列表中出现多次,也会发生这种情况。

无论哪种方式,为了使您的比较函数成为一个正确的,表现良好的比较函数,您需要处理与自身进行比较的元素的情况。

答案 2 :(得分:2)

虽然没有严格保证,但我很确定List的Sort方法永远不会调用你的compare方法来比较一个对象与它自己,除非该对象碰巧多次出现在列表中。我的结论基于List.Sort是使用QuickSort算法(根据MSDN)实现的,从不比较 通常不涉及将相同的元素与自身进行比较(我能想到的任何其他记录的排序算法都没有)。 (编辑:似乎微软的实现确实将元素与自身进行了比较。请参阅上面接受的答案。)

但是,良好的编码实践将要求您的IComparer实现应该能够处理在两个参数中传递相同的对象,否则您的实现不会完全填充IComparer定义的协定。它可能适用于您的场景,但您将依赖于排序方法的实现细节(将来可能会更改),并且您将无法在没有此类情况的其他场景中使用IComparer实现。保证(或者更糟糕的是,您或其他人使用它并可能造成难以发现的错误)。

答案 3 :(得分:1)

另一个答案,这个基于the XML part of ECMA-335,BCL(基类库)的规范。虽然不能保证与实际实现有什么关系,但这是有权威的。规范只说明了:

  

最坏的情况是,此操作为O(n ^ 2),其中n是要排序的元素数。平均而言,它是O(n log n)。

虽然这是QuickSort的暗示,但绝对不能保证。该规范也不需要以Array.Sort来实现。

底线:就规范而言,将项目与自身进行比较是完全可以的。