【问题标题】:Why is radix sort O(nd) but merge sort isn't O(d*nlogn)?为什么基数排序是 O(nd) 而归并排序不是 O(d*nlogn)?
【发布时间】:2018-11-06 07:46:56
【问题描述】:

通常当人们谈论排序算法的复杂性时,我看到这样的解释:

基数排序的复杂度是O(nd),其中n是 列表,d 是位数

合并排序的复杂度是O(n log n),其中n是 列表

这几乎是为了证明基数排序通常比合并排序慢,尽管它没有任何意义。

有两种情况:

案例 1: 我们正在对具有四个字节的普通整数进行排序。 在这里,比较需要固定的时间,所以O(n log n) 描述归并排序是有意义的。但是,在对普通整数进行排序时,O(nd) 中的d 是一个常数(对于基数 16 或 16,对于基数 2,可能是 4。无论哪种方式,它都是一个常数,并且 bin 排序中的 bin 数量由基数调用排序比例以弥补这一点)。那么,说基数排序是O(n) 而归并排序在客观上具有更差的复杂性,O(nlogn) 不是更有意义吗?

案例 2: 我们正在对字符串进行排序,可以将其视为具有基本 ASCII 中任意位数的数字。 在这里,比较需要O(d) 时间,因为更糟糕的情况是将AAAAAAAABAAAAAAAAC 进行比较,这可能需要很长时间。 在这种情况下,说基数排序具有复杂性O(nd) 是完全有道理的,因为d 随输入而变化。 但是,由于比较时间不再恒定,因此在这种情况下不应该考虑合并排序O(d*nlogn)吗?

在我看来,人们不相信基数排序的使用速度足够快,并且他们通过模棱两可的复杂性描述使其看起来比基于比较的排序更糟糕来证明它的大时间常数是合理的。

我为糟糕的格式道歉,我不确定如何让它在 stackoverflow 上看起来更好

【问题讨论】:

  • 格式化只是使用文本框上方的按钮......除此之外,实际的问题是什么?基数排序需要固定大小的键;当你有固定大小的键时使用它...
  • 问题出在通常包含代码的框中,但我用它来保持我的空白保持完整
  • 另外,适应基数排序来对可变长度的整数字符串进行排序是微不足道的——它仍然需要 O(n) 时间。一种方法是先按长度对它们进行排序,只要它们的长度小于 2^32,也可以使用基数排序。
  • @MitchWheat Radex 排序也可以用于字符串,请参阅here
  • 如果你的字符串有一个概率模型,那么合并排序中字符串比较的平均成本通常为 O(1),或者至少

标签: algorithm sorting merge mergesort radix-sort


【解决方案1】:

逐个字符(或逐个数字)比较时的合并排序将是O(d n log n) 操作。但是您可以对任何类型的对象进行排序,并且比较可以是这些对象上的任何函数,因此这样的表示会过于具体 - 您需要一些其他复杂性来使用不同的比较方法来表示相同的合并排序算法。

comparisons的数量来表示复杂性更有意义,所以你可以说mergesort总是O(n log n)比较。

比较通常也被认为是一个非常快的操作,即恒定时间(即使这不是一般规则)。另一方面,基数排序需要对每个数字的输入进行循环——你不能说有多少循环并不重要。

比较归并排序和基数排序的复杂度在一定程度上是比较苹果和橘子。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 2021-08-13
    • 2020-01-10
    • 1970-01-01
    相关资源
    最近更新 更多