【问题标题】:How many times the CompareTo method is called when a collection is sorted?对集合进行排序时调用 CompareTo 方法多少次?
【发布时间】:2012-11-25 01:16:22
【问题描述】:

如果一个类型实现了IComparable<T>,并且您有一个包含 100 个元素的此类型的集合。当你在这个集合上调用 Sort 方法时,CompareTo 方法会被调用多少次,如何调用?会这样用吗?

CompareTo(item0, item1);
CompareTo(item1, item2);
CompareTo(item2, item3);
CompareTo(item3, item4);
...
CompareTo(item97, item98);
CompareTo(item98, item99);

编辑:基本上我要做的是将这种排序方式转变为基于值的排序,在其中我为每个项目分配一些值,然后对它们进行排序。很难解释,但我无法使用基于 -1,0,1 的排序函数来解决这个问题。但我只有一个 CompareTo 函数,我需要用它来对项目进行排序。所以我需要为每一项生成一些值,然后程序会从最小值到最大值进行排序。

【问题讨论】:

  • 这完全取决于 IComparable 的特定实现,不是吗?
  • 我不这么认为,因为 CompareTo 总是会返回 -1、0 或 1。
  • @mwilson 实际上这完全取决于Sort 方法(使用的算法)和数据本身:)
  • 这取决于排序算法和数据的未排序程度。
  • 您是否要对未为任何 2 个元素定义顺序的项目进行排序?正常排序算法要求比较是可传递的(a

标签: c# .net sorting collections icomparable


【解决方案1】:

好吧,您不能 100% 确定(对于大多数排序算法),因为这取决于数据。例如,某些排序算法只会对已经排序的数据执行 N(N 是集合的大小)比较,但如果不是,则需要更多。

常用的排序算法,如MergeSort、QuickSort、HeapSort都是O(n*log(n)),也就是说比较的次数会是item数乘log的顺序项目数量的基础。 (这些算法的对数基数将是 2。)虽然这并不准确,但它会随着这种关系而扩展。

如果您对特定排序操作调用它的次数感兴趣,您可以使用如下内容:

public class LoggingComparer<T> : IComparer<T>
{
    private IComparer<T> otherComparer;
    public LoggingComparer(IComparer<T> otherComparer)
    {
        this.otherComparer = otherComparer;
    }

    public int Count { get; private set; }

    public int Compare(T x, T y)
    {
        Count++;
        return otherComparer.Compare(x, y);
    }
}

它将包装另一个比较器,但也会计算比较调用的数量。这是一个示例用法:

var list = new List<int>() { 5, 4, 1, 2, 3, 8, 7, 9, 0 };

LoggingComparer<int> comparer = new LoggingComparer<int>(Comparer<int>.Default);
list.Sort(comparer);
Console.WriteLine(comparer.Count);

【讨论】:

  • 对数的底数真的有区别吗? O 表示法仅计算相对数字。 IE。它告诉您当您增加n 时操作会变得多么复杂,但它不会告诉您特定n 需要多少基本操作。
  • @OlivierJacot-Descombes 通常,没有人关心操作的确切数量,只关心增长模式。
  • @OlivierJacot-Descombes 这完全取决于您想要获得的详细程度。在最基本的层面上,big-oh 会说不定义日志的基础,但在实践中,提供 big-oh 通常包含的更多信息(例如日志的基础)可能很有用。您想要多详细取决于上下文。
【解决方案2】:

支持 Servy 的回答。无论排序算法的比较操作的渐近复杂度是多少,这就是可能对 CompareTo() 进行多少次调用。请注意,这通常是一种增长模式,而不是确切的操作数量。

【讨论】:

  • 有点。在确定算法的渐近复杂度时,您通常会预先说明您正在考虑“一个单元”的操作类型。对于排序算法,这通常只是CompareTo 调用,但它可能(对于某些算法)包括其他操作。对于非排序算法,它可能是......任何东西。
  • @Servy,即使有你的答案,你也必须考虑你是计算交换还是比较。以插入排序为例。我指的是比较,因为这通常是排序算法中成本最高的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多