每种sortingalgorithm何时使用?
当一个特定的sortingalgorithm优于其他的时候,什么是用例 – merge sort
与quick sort
与heap sort
intro sort
等等?
根据数据结构的大小,types,可用内存和caching以及CPU性能,是否有推荐的使用指南?
首先,一个定义,因为它是非常重要的: 稳定的sorting是保证不重新排列具有相同键的元素。
build议:
快速sorting:当你不需要一个稳定的sorting和平均情况下性能比最坏的情况下性能更重要。 在最坏的情况下,快速sorting是O(N log N),O(N ^ 2)。 一个好的实现使用O(log N)辅助存储以堆栈空间的formsrecursion。
合并sorting:当您需要稳定的O(N日志N)sorting时,这是您唯一的select。 唯一的缺点是它使用O(N)辅助空间,并且具有比快速sorting略大的常量。 有一些就地合并sorting,但AFAIK他们都不稳定或比O(N日志N)差。 即使是O(N log N)到位sorting也比普通的旧归并sorting大得多,它们比理论algorithm更具有理论上的好奇心。
堆sorting:当你不需要一个稳定的sorting,你更关心最坏的情况下性能比平均情况下的performance。 它保证为O(N log N),并使用O(1)辅助空间,这意味着在非常大的input上不会意外地耗尽堆或堆栈空间。
Introsort:这是一种快速sorting,在某个recursion深度之后切换到堆sorting,以避开快速sorting的O(N ^ 2)最差的情况。 它几乎总是比简单的旧的快速sorting,因为你得到一个快速sorting的平均情况,并保证O(N日志N)性能。 可能使用堆sorting而不是这个的唯一原因是在O(log N)堆栈空间实际上很重要的严重内存受限的系统中。
插入sorting :当N保证很小时,包括作为快速sorting或合并sorting的基本情况。 虽然这是O(N ^ 2),它有一个非常小的常数,是一个稳定的sorting。
气泡sorting,selectsorting :当你做一些快速和肮脏的事情,出于某种原因,你不能只使用标准库的sortingalgorithm。 这些插入sorting的唯一好处是稍微容易实现。
非比较sorting:在一些相当有限的条件下,可以打破O(N log N)屏障并按照O(N)sorting。 以下是一些值得一试的例子:
计数sorting:当您sorting有限范围内的整数。
基数sorting:当log(N)明显大于K时,其中K是小数位数。
桶sorting:当你可以保证你的input是近似均匀分布的。
sorting-algorithms.com上提供了一组用于不同types数据和algorithm的animation
快速sorting通常是平均速度最快的,但它有一些非常讨厌的最坏情况的行为。 所以如果你必须保证没有错误的数据给你O(N^2)
,你应该避免它。
合并sorting使用额外的内存,但特别适合外部sorting(即不适合内存的巨大文件)。
堆sorting可以就地sorting,并没有最坏的情况二次行为,但在大多数情况下平均速度比快速sorting慢。
如果只涉及有限范围内的整数,则可以使用某种基数sorting使其速度非常快。
在99%的情况下,对于通常基于快速sorting的图书馆sorting你会没事的。
维基百科页面sortingalgorithm有一个很好的比较图表。
http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms
提供的比较/animation链接不考虑何时数据量超过可用内存 – 在这一点上数据传递的数量(即I / O成本)在运行时占主导地位。 如果您需要这样做,请阅读“外部sorting”,通常涵盖合并和堆sorting的变体。
@dsimcha写道:计数sorting:当你正在sorting有限范围的整数
我会改变:
计数sorting:对正整数进行sorting时(归因于鸽子,0 – Integer.MAX_VALUE-2)。
在线性时间内,您始终可以将最大值和最小值作为效率启发式。
中间数组还需要至lessn个额外的空间,并且显然是稳定的。
/** * Some VMs reserve some header words in an array. * Attempts to allocate larger arrays may result in * OutOfMemoryError: Requested array size exceeds VM limit */ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
(尽pipe它实际上将允许MAX_VALUE-2)请参阅: Java数组是否具有最大大小?
另外我会解释,基数sorting的复杂性是O(WN)为n个键,这是整数字的大小W。 有时w表示为一个常量,这将使基数sorting比基于比较的最佳sortingalgorithm更好(对于足够大的n),这些algorithm全部执行O(n log n)比较来对n个键进行sorting。 但是,一般情况下w不能被认为是一个常数:如果所有的n个密钥都是不同的,那么对于一个随机访问机器来说,w必须至lessloggingn,以便能够将它们存储在存储器中,这至less给出时间复杂度O (n log n)。 (来自维基百科)