当数字的基数等于要排序的数字的数量时,为什么基数排序的运行时间最小化?

时间:2016-03-24 00:01:10

标签: algorithm sorting

在CSLR第199页中,他们说:

  

引理8.4:给定n个b位数和任何正整数r< = b,如果稳定排序,则RADIX-SORT在O((b / r)(n + 2 ^ r))时间内正确排序这些数字它使用O(n + k)时间作为0到k范围内的输入。

作为理解这一点的一个例子,有以下内容,我跟随我认为的CSLR推理(并提出问题):

我们从n个32位数字开始(b = 32)。我们有n个数字可以取值0到2 ^ 32 - 1.如果我们运行radix-sort,它将涉及一次遍历数字,其中count-sort与变量k一起使用(表示范围0到k)其中n个数字等于2 ^ 32-1。计数排序是O(n + k),所以如果k>> n,对于可变大小的n,我们的运行时间非常糟糕。

我们现在所做的是将每个32位数字分成四个8位数字。这意味着r = 8,因此这四个数字中的每一个现在具有0到2 ^ 8-1 = 255的范围.d = b / r = 32/8 = 4是n个数中的每一个中的数字位数。

我的第一个问题是:我们可以将数字256视为四个8位数字中每一个的新基数吗?我们现在有四个256位数吗?

现在当我们使用基数排序时,我们必须做四次传递而不是一次传递(计数排序使用四次)。每次传递都是O(n + k),但现在k是2 ^ 8 - 1 = 255而不是2 ^ 32 - 1.所以总运行时间是O(4 *(n + 255)。

因此,当我们将初始数字拆分为较小的r位数时,我们会增加基数排序次数,但会减少计数排序中的值范围。似乎有一个最佳的r,可以最大限度地减少运行时间。

**第二个问题:第99页有一个段落似乎认为r的这个值可以使表达式O((b / r)(n + 2 ^ r))最小化。有人可以提供更好的解释吗?我无法理解它。 **

  

对于给定的n和b值,我们希望用r选择r的值   &lt; = b,使表达式(b / r)最小化(n + 2 ^ r)。如果b < LG(N),   那么对于任何r&lt; = b的值,我们得到(n + 2 ^ r)= O(n)。从而,   选择r = b产生的运行时间为(b / b)(n + 2 ^ b),即   渐近最优。如果b> = lg(n),则选择r = lg(n)   给出了恒定因子内的最佳时间,我们可以看到   如下。选择r = lg(n)产生O(bn / lg(n))的运行时间。如   我们将r增加到高于lg(n),分子中的2 ^ r项增加   比分母中的r项更快,因此增加r以上   lg(n)产生Omega的运行时间(bn / lg(n))。如果相反,我们去了   将r降低到lg(n)以下,则b / r项增加,n + 2 ^ r   术语保留在O(n)。

在麻省理工学院开放式课件(第7讲课程笔记)中,在他们的一门算法课程中,他们将最小化显示略有不同: count-sort在O(n + b)中运行,其中b是表示数字的基数。因此,如果n个数字在0到k的范围内,则每个数字具有k个数字的d = log base b,其中每个数字是0到b-1之间的数字。所以b现在是CSLR的前一个例子中的k。基数排序进行计数排序,因此总运行时间为O(d(n + b))= O((n + b)*(k的基数b))。当b被选择为n时,这被最小化。 这与上面关于同一主题的CSLR讨论有何关联。

1 个答案:

答案 0 :(得分:1)

部分答案在这里。第一个问题 - 256将是基数,并且在32位整数中将有四个8位数字。从文章中遗漏的是,它需要对数据进行一次读取传递以创建计数矩阵,然后将其转换为索引(或指针)矩阵。在这种情况下,矩阵是[4] [256]。创建矩阵后,需要4个读/写基数排序传递来对数据集进行排序。

第二个问题 - 对于基于数学的解释,(b / r)的导数(n + 2 ^ r)=(b(2 ^ r(r log(2) - 1) - n))/ r ^ 2。当导数== 0时出现最小值(或最大值),这发生在2 ^ r(r log(2) - 1) - n = 0时。对于n == 2 ^ 20(约1百万),r~ = 16.606232导致O()〜= 2212837.一些示例值和O():

 r   O
18   2330169
17   2220514
16   2228224
15   2306867
12   2807125
 8   4195328

但是,由于缓存问题,r与n的最佳值变小。在我的系统(Intel 2600K,3.4ghz)上,对于n = 2 ^ 20,r = 8是最快的。在n = 2 ^ 24附近,r = 10.67,使用3个场10,11,11是最快的。在n = 2 ^ 26附近,r = 16是最快的。同样,由于缓存问题,性能没有太大差异,r = 8与r = 16相比不到10%。