6

我正在探索以下算法:

  1. 计数排序
  2. 基数排序
  3. 桶排序

我知道这三个都能够在最好的情况下以线性时间运行,但是我很难理解这些情况何时发生,除了计数排序的情况。

这是我对计数排序的理解,以及如果可能的话,我希望如何回答其他两种算法:

当您希望排序的信息之间没有大的差距时,计数排序以线性时间运行。例如 1、10^5 和 545 等会创建一个大数组,并且使用内存和遍历效率不高,因此这将是使用计数排序的“最坏情况”,因此最好的情况是当差距很小。

如果有人可以帮助我了解线性时间发生时基数和桶排序最佳情况的条件,我将不胜感激。

4

1 回答 1

6

让我们从独立分析每个算法开始,看看我们是否可以确定它们在什么情况下会以线性时间运行。

首先,让我们看一下计数排序。该算法的工作原理如下:

  • 找到要排序的最大整数。
  • 创建一个数组,每个整数一个槽进行排序。
  • 遍历主数组,用每个元素的频率更新第二个数组。
  • 通过用每个元素的适当数量的副本填充输出数组来构造排序数组。

第一步可以通过迭代主数组在 O(n) 时间内完成。假设数组中的最大值是 U。在这种情况下,第二步需要时间 O(U),因为我们必须将数组元素归零。第三步需要时间 O(n)。最后一步需要时间 O(n + U),因为我们只访问频率数组的每个元素一次 (O(U)),并且总共 n 次写入输出数组 O(n)。这意味着总运行时间为O(n + U)。请注意,这取决于需要排序的元素总数(较大的数组需要更长的排序时间)和数组中元素的大小(较大的数字将需要更多的运行时间)。

如果我们希望这个运行时间为 O(n),我们需要要求 U = O(n)。这样,我们就会得到 O(n + U) = O(n + n) = O(n)。这意味着您需要使数组中最大元素的大小以与数组长度增加的速度大致相同的速度增长。例如,如果您保证数组中的所有元素都在 1 .. n 范围内,那么计数排序将需要 O(n) 时间才能完成。这些元素如何在该范围内分布并不重要。


基数排序本质上是通过一遍又一遍地重复进行计数排序来工作的,对数组中要排序的数字的每个数字一次。基数排序背后的关键思想是使先前算法中的 U 值尽可能低。通过选择一些固定的基数,U 的值被限制在某个常数上。例如,如果您使用二进制基数排序并且一次只进行一位,则要排序的数组的每个元素本质上都被视为 0 或 1。这意味着每一轮基数排序需要时间 O( n) 完成。然后,对整个数组进行排序所需的轮数由数组中最大数的位数给出,即 Θ(log U)。这意味着算法的总运行时间最终为 O(n log U)。

这次的好处是log U的增长比U慢得多。例如,2 300大约是宇宙中原子的总数,但lg (2 300 ) = 300,相当小。

有些人会声称 log U 在任何固定计算机上都是一个常数。在 32 位计算机上,所有整数都是 32 位(除非您使用的是任意精度整数库,我们现在将忽略它),而在 64 位系统上,所有整数都是 64 位。在第一种情况下,log U = 32,在第二种情况下,U = 64。您可以声称对于固定系统,基数排序总是需要线性时间,因为运行时间将为 O(n)。但是,常数因系统而异。如果你更有理论头脑并且想要更精确,你可以说只要 log U = O(1),基数排序就会在线性时间内运行,因为那样 O(n log U) = O(n)。这意味着如果您对数字中的位数有任何恒定的上限,则可以保证基数排序将在线性时间内运行。


桶排序算法类似于基数排序,不同之处在于它使用最高有效位而不是最低有效位来分配元素。这意味着分析与以前几乎相同 - 只要 log U = O(1),算法在线性时间内运行。


希望这可以帮助!

于 2013-04-02T04:01:54.277 回答