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

时间:2010-08-25 14:23:59

标签: java algorithm sorting collections

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

伪代码:

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

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

4 个答案:

答案 0 :(得分:45)

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

对于小N,插入排序实际上确实击败了合并排序。几乎排序的数组也更快。

这是a quote

  

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

     

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

以下是Best sorting algorithm for nearly sorted lists论文的另一个引用:

  

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

这意味着,在实践中:

  • 具有较高渐近上限的某些算法 A 1 可能优于另一种已知算法 A 2 渐近上界
  • 某些混合算法可能会根据输入大小调整不同的算法

相关问题


数值示例

让我们考虑这两个功能:

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

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

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

请注意,在x=0..5f(x) <= g(x)之间,但对于任何较大的xf(x)很快就会超过g(x)

类似地,如果 A 1 是具有低开销的二次算法,并且 A 2 是高开销的线性算法,对于较小的输入, A 1 可能比 A 2 更快。

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

已经对排序算法进行了许多测试和比较,并且决定因为插入排序对小型数组进行合并排序,因此为Arrays.sort实现两者都是值得的。

答案 1 :(得分:5)

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

答案 2 :(得分: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.

答案 3 :(得分:1)

看起来他们认为mergeSort(array)对于短阵列来说速度较慢。希望他们真的测试过。