什么时候应该实现一种简单或高级的排序算法?
Posted
技术标签:
【中文标题】什么时候应该实现一种简单或高级的排序算法?【英文标题】:When should one implement a simple or advanced sorting algorithm? 【发布时间】:2018-02-19 19:30:54 【问题描述】:除了明显的“元素多时速度更快”。与高级排序算法 (O(N log N)) 相比,什么时候使用简单排序算法 (0(N^2)) 更合适?
我已经阅读了很多关于例如插入排序是首选的内容,当你有一个几乎排序的小数组时,因为你得到最好的情况 N。为什么使用快速排序不是很好,例如,当你'有说20个元素。不仅仅是插入或快速,而是与高级算法相比,更简单的算法何时以及为什么有用?
编辑:如果我们正在使用例如一个数组,那么我们拥有哪个数据输入是否重要?例如对象或原始类型(整数)。
【问题讨论】:
使用 20 个元素,您不会注意到效率上的差异,因此您可以使用任何您想要的算法。对于几乎已排序的列表,插入排序更好,因为它将在 N 次操作中完成,而快速排序将始终为 nlogn 如果它像你的例子一样小,简单的排序就可以了。但是一些服务器托管合同基于处理时间,从长远来看,从较大的查询/排序中节省几秒钟可以节省 $$。 有时实现一个低效的算法会更简单,比如排序 O(n^2),而实现 O(n log n) 则有点困难。如果您因为输入较少而不需要那么高的效率,那么您可以选择更易于维护的代码。 ***.com/questions/736920/… @aeliton 我不相信。您能否为我命名一个体面的编程环境,其中还没有为了您的方便而实现的高效排序例程? 【参考方案1】:big-oh 表示法捕获算法的运行时成本对于较大的 N 值。它在测量小值的算法运行时效果较差。
从一种算法到另一种算法的实际转换并非易事。对于较大的 N,N 的影响确实占主导地位。对于小数字,更复杂的效果变得非常重要。例如,某些算法具有更好的缓存一致性。当您对数据有所了解时,其他人是最好的(例如您的插入排序示例,当数据几乎排序时)。
平衡也会随着时间而改变。过去,CPU 速度和内存速度更接近。缓存一致性问题不是问题。在现代,CPU 速度通常已将内存总线抛在后面,因此缓存一致性更为重要。
因此,对于何时应该使用一种算法而不是另一种算法,没有一个明确而枯燥的答案。唯一可靠的答案是分析您的代码并查看。
为了娱乐:几年前我正在研究动态不相交森林问题。我遇到了一篇最先进的论文,该论文允许一些操作以 O(log log N / log^4N) 之类的愚蠢方式完成。他们做了一些真正出色的数学运算才能到达那里,但有一个问题。这些操作非常昂贵,以至于对于我的 50-100 个节点的图,它比我最终使用的 O(n log n) 解决方案慢得多。这篇论文的解决方案对于在超过 500,000 个节点的图上进行操作的人来说更为重要。
【讨论】:
【参考方案2】:在编写排序算法时,您必须考虑实现实际算法所需的工作量与其实际速度。对于大 O,实现高级算法的时间将被减少的排序时间所抵消。对于小O,比如20-100个项目,差别很小,所以走更简单的路线会好很多。
【讨论】:
调用内置排序例程的工作比实现自己的工作要少。除非有非常好的具体理由不这样做,否则您应该始终做最简单有效的事情。【参考方案3】:首先,O-Notation 让您了解最坏的情况。因此,如果数组几乎已排序,则执行时间可能接近线性时间,因此它会比快速排序更好。 如果 n 足够小,我们会考虑其他方面。由于调用了所有递归,诸如快速排序之类的算法可能会更慢。在这一点上,它取决于操作系统如何处理递归,最终可能比插入排序中所需的简单算术运算要慢。更不用说递归算法所需的额外内存空间了。
【讨论】:
【参考方案4】:在超过 99% 的情况下,您根本不应该实现排序算法。
改为使用您语言的标准库中的标准排序算法。在一行代码中,您可以使用经过测试和优化的实现,即O(n log(n))
。它可能实现了您不会想到的技巧。
对于外部排序,我不时使用 Unix sort
实用程序。除了非直观的 LC_ALL=C
环境变量,我需要让它运行,它非常有用。
在您实际需要实现自己的排序算法的任何其他情况下,您实现的内容将由您的精确需求驱动。在两年的编程中,我不得不为生产代码处理一次。 (这是因为由于一系列复杂的原因,我需要在一台没有足够磁盘空间来存储未压缩数据的机器上对压缩数据进行排序。我使用了归并排序。)
【讨论】:
以上是关于什么时候应该实现一种简单或高级的排序算法?的主要内容,如果未能解决你的问题,请参考以下文章