Algorithm 何时使用非比较排序而不是比较排序

Algorithm 何时使用非比较排序而不是比较排序,algorithm,sorting,Algorithm,Sorting,在课堂上,为了避免所有基于比较的排序的omega(nlogn)下限,我们学习了一系列新的非比较排序。但我有点不清楚的是,什么时候使用哪一系列的排序算法是赞成和反对的 不能调整任何数据集,以便使用非比较排序算法(基数、桶、键索引)?如果是这样的话,比较排序的意义何在 很抱歉,这是一个如此基本的问题,但我确实在网上找不到任何东西。非比较排序的问题是,它们的复杂性通常取决于输入大小以外的其他参数。例如,基数排序有O(kn)复杂度,其中k是元素中的最高位数——问题是,k与n的关系如何。如果k与n大致相同

在课堂上,为了避免所有基于比较的排序的
omega(nlogn)
下限,我们学习了一系列新的非比较排序。但我有点不清楚的是,什么时候使用哪一系列的排序算法是赞成和反对的

不能调整任何数据集,以便使用非比较排序算法(基数、桶、键索引)?如果是这样的话,比较排序的意义何在


很抱歉,这是一个如此基本的问题,但我确实在网上找不到任何东西。

非比较排序的问题是,它们的复杂性通常取决于输入大小以外的其他参数。例如,基数排序有O(kn)复杂度,其中k是元素中的最高位数——问题是,k与n的关系如何。如果k与n大致相同,则算法变为O(n^2)。

非基于比较的排序算法对输入进行假设。为了确保线性时间复杂度,输入的所有元素都必须在一个恒定长度的范围内。另一方面,基于比较的排序算法对输入没有任何假设,并且能够处理任何情况。基于非比较的排序算法通常以额外的内存成本和输入缺乏通用性为代价。

不是每一组项目都可以调整为以有效的方式用于非比较排序。例如,对任意精度的数字进行排序需要在bucket sort中多次运行循环,从而降低性能

世界基数排序的问题在于,它们必须检查被排序的每个项目的每个元素。另一方面,基于比较的排序可以跳过相当数量的子元素(数字、字符等)。例如,当比较函数检查两个字符串时,它会在第一个差值处停止,跳过两个字符串的尾部。另一方面,Bucket sort必须检查每个字符串*中的所有字符

一般来说,追求最佳渐进复杂度并不总是一个好策略:使用明显更复杂的算法得到回报的N值往往过高,无法使更复杂的算法实用。例如,quicksort具有非常糟糕的时间复杂度,但由于其非常低的开销,它平均可以轻而易举地击败大多数其他算法,这使得它在大多数实际情况下都是一个不错的选择。

*在实践中,只要存储桶中的项目数下降到某个阈值以下,就切换到基于比较的排序,从而避免了对所有子元素(数字、字符等)进行排序的需要。这种混合方法优于普通的基于比较的排序和普通的桶式排序。

当您懒得编写非基于比较的排序时,可以使用基于比较的排序

基于比较的排序天生较慢;他们需要多次调用输入元素上的比较器,每次调用只提供一位基于比较的排序信息。一个正确的基于比较的排序必须平均累积关于其输入的log_2(n!)~=n个log(n)位信息

现在,所有数据在机器中都有一个表示。您可以根据特定类型的数据、数据的表示形式以及用于排序的机器来定制排序算法,而且,如果您知道自己在做什么,您通常会击败任何基于比较的排序算法

然而,性能并不是一切,在某些情况下(事实上,我见过的大多数情况下),性能最好的解决方案并不是正确的解决方案。好的基于比较的排序可以使用一个黑盒比较器,它们将在一个小的常量乘以n个log(n)比较中对输入进行排序。对于几乎所有的应用程序来说,这已经足够好了


编辑:以上仅适用于内部排序,其中您有足够的RAM来存储整个输入。外部排序(比如溢出到磁盘)通常应该通过一次读取大约半个RAMful的数据来完成,使用一种基于非比较的排序,然后将排序结果写出来。同时要注意将排序与输入和输出重叠。最后,进行(基于比较的)n向合并。

通过选择特定的排序算法,可以用内存换取速度,反之亦然。你的问题的局限性使得某些算法不切实际。你能举一个键和值的数据集的例子,其中非比较排序不起作用吗?难道不能调整任何数据集,使键适合非比较排序吗?假设我们要对N个整数进行排序,其范围未知。在这种情况下,我们只能使用基于比较的算法。换句话说,无论你如何调整输入,一般的排序问题可能只能在O(NlgN)时间内解决。输入的所有元素都需要在一个小范围内,以确保比较排序的O(n log(n))时间复杂度,因为你调用了比较器θ(n log(n))次。当然,bucketsort可以从MSD到LSD工作,当桶变得足够小时,使用其他排序(比如插入排序)。因此,如果使用它对字符串进行排序,它可能只读取每个字符串的前几个字节。大多数快速排序实现,除非专门针对排序字符串,否则不会执行此优化,并且在快速排序的更深层递归中,比较字符串的第一个差异在字符串中逐渐加深。所以,尽管我同意你的总体结论,但我不相信这个例子。@rici这是一个很好的评论,非常感谢!我同意,我的快速排序示例有点误导,因为我引入它是为了说明一个与原始问题没有直接关系的普遍观点——特别是,具有更高渐近复杂度的低开销算法可以击败不可靠的算法