为啥 java.util.Arrays.sort(Object[]) 使用 2 种排序算法?

Posted

技术标签:

【中文标题】为啥 java.util.Arrays.sort(Object[]) 使用 2 种排序算法?【英文标题】:Why does java.util.Arrays.sort(Object[]) use 2 kinds of sorting algorithms?为什么 java.util.Arrays.sort(Object[]) 使用 2 种排序算法? 【发布时间】:2010-08-25 14:23:58 【问题描述】:

我发现java.util.Arrays.sort(Object[]) 使用了 2 种排序算法(在 JDK 1.6 中)。

伪代码:

if(array.length<7)
   insertionSort(array);
else
   mergeSort(array);

为什么这里需要2种排序?为了效率?

【问题讨论】:

【参考方案1】:

请务必注意,O(N log N) 算法在实践中并不总是比O(N^2) 算法更快。这取决于常数,以及所涉及的N 的范围。 (请记住,asymptotic notation 衡量的是相对增长率,而不是绝对速度)。

对于小的N,插入排序实际上胜过归并排序。对于几乎排序的数组,它也更快。

这里是a quote:

虽然它是具有O(N^2) 最坏情况时间的基本排序算法之一,但插入排序是当数据接近排序(因为它是自适应的)或当问题规模很小(因为它的开销很低)。

由于这些原因,并且由于它也很稳定,插入排序通常用作递归基本情况(当问题规模较小时),用于更高开销的分治排序算法,例如合并排序或快速排序.

这是来自Best sorting algorithm for nearly sorted lists论文的另一句话:

直接插入排序最适合小型或非常接近排序的列表

这意味着,在实践中:

具有更高渐近上限的某些算法 A1 可能比具有更高渐近上限的另一种已知算法 A2 更可取下渐近上界 也许 A2 实现起来太复杂了 或者在考虑的N范围内可能无关紧要 参见例如Coppersmith–Winograd algorithm 一些混合算法可能会根据输入大小调整不同的算法

相关问题

Which sorting algorithm is best suited to re-sort an almost fully sorted list? Is there ever a good reason to use Insertion Sort?

数值示例

让我们考虑这两个函数:

f(x) = 2x^2;该函数具有二次增长率,即“O(N^2)g(x) = 10x;该函数具有线性增长率,即“O(N)

现在让我们一起绘制两个函数:

来源: WolframAlpha: plot 2x^2 and 10x for x from 0 to 10

请注意,在x=0..5f(x) &lt;= g(x) 之间,但对于更大的xf(x) 会很快超过g(x)

类似地,如果A1是一个开销很小的二次算法,而A2是一个线性算法开销较大,对于较小的输入,A1可能比A2快。 p>

因此,如果您选择这样做,您可以创建一个混合算法A3,它只需根据输入的大小选择两种算法之一.这是否值得努力取决于所涉及的实际参数。

已经对排序算法进行了许多测试和比较,并确定因为插入排序优于合并排序,所以对于Arrays.sort,两者都实现是值得的。

【讨论】:

您可能想将上面的图表与我在插入排序和 Java 排序之间进行的一些实际测量进行比较:javamex.com/tutorials/collections/… 除了这个出色的分析之外,请注意,常用的插入排序有 两种不同的——常规插入排序和“二元插入排序”,您可以在其中找到位置通过二进制搜索插入,然后移动所有内容以腾出空间。如今,在大多数处理器上,交换比比较快,而二进制插入排序减少了比较的次数。因此,通常情况下,您会发现二进制插入排序。【参考方案2】:

这是为了速度。 mergeSort 的开销足够高,对于短数组,它会比插入排序慢。

【讨论】:

【参考方案3】:

引用自:http://en.wikipedia.org/wiki/Insertion_sort

Some divide-and-conquer algorithms such as quicksort and mergesort sort by 
recursively dividing the list into smaller sublists which are then sorted. 
A useful optimization in practice for these algorithms is to use insertion 
sort for sorting small sublists, where insertion sort outperforms these more 
complex algorithms. The size of list for which insertion sort has the advantage 
varies by environment and implementation, but is typically between eight and 
twenty elements.

【讨论】:

【参考方案4】:

似乎他们认为mergeSort(array) 对于短数组来说较慢。希望他们真的对此进行了测试。

【讨论】:

以上是关于为啥 java.util.Arrays.sort(Object[]) 使用 2 种排序算法?的主要内容,如果未能解决你的问题,请参考以下文章

我们可以在java中使用引用传递吗?如果否 java.util.Arrays.sort 如何工作?

java_Arrays.sort()方法

有朋友能详细介绍一下java中sort的用法吗

Java Arrays.sort源代码解析

Java:使用sort方法对整个数组或部分数组进行排序的问题

Java比较器