为什么Arrays.sort是快速排序算法,为什么不是另一种排序算法呢?

时间:2010-11-29 15:09:15

标签: java algorithm

为什么呢?是更快还是更有效?

对于具有一个核心的系统,我们可以使用quicksort。我们应该在具有两个内核,四个内核或八个内核的系统上使用什么?

12 个答案:

答案 0 :(得分:34)

Quicksort具有完全就位的优势,因此它不需要任何额外的存储,而mergesort( 实际上由Arrays.sort()用于对象数组)和其他(所有?)保证O(n * log n)算法至少需要一个完整的数组副本。对于对非常大的原始数组进行排序的程序,这意味着可能会使整体内存使用量翻倍。

答案 1 :(得分:18)

答案在Jon L. Bentley和M. Douglas McIlroy的“Engineering a Sort Function”中,排序函数引用。

  为了获得更好的qsort,我们发现1983年在Berkeley编写的qsort会在包含少量元素重复多次的数组上消耗二次时间 - 特别是随机零和1的数组。事实上,在十几个不同的Unix库中,我们发现没有qsort不能轻易被驱动到二次行为;所有这些都来自第七版或1983年的伯克利函数......

     

无法找到足够好的qsort,我们打算建立一个更好的。该算法应该避免合理输入的极端减速,并且应该在“随机”输入上快速。它在数据空间和代码空间中也应该是高效的。排序不一定稳定;它的规范不保证保持相等元素的顺序。

由于Java是在20世纪90年代初创建的,所以替代品是heapsort和mergesort。 Mergesort不太理想,因为它需要额外的存储空间。 Heapsort具有更好的最坏情况性能(O(n log n)O(n^2)相比),但在实践中表现更慢。因此,如果您可以通过良好的启发式方法控制最坏情况的性能,那么可以采用优化的快速排序方式。

Java 7正在转向Timsort,它是在1993年发明的(2002年在Python中实现),并且具有O(n log n)的最差情况并且是稳定的类型。

答案 2 :(得分:14)

Quicksort具有O(n log n)平均值和O(n ^ 2)最差情况性能,这是排序算法可能的最佳“平均情况”,还有其他排序算法具有此性能,但快速排序趋势比大多数人表现更好。

请参阅:http://en.wikipedia.org/wiki/Quicksort

答案 3 :(得分:10)

这是调整快速排序。如果您真的感兴趣,可以阅读文档中提到的材料。

  

排序算法是一个经过调整的快速排序,改编自Jon L. Bentley和M. Douglas McIlroy的“Engineering a Sort Function”,Software-Practice and Experience,Vol。 23(11)P。1249-1265(1993年11月)。

这里有一点解释 - 调整后的版本在许多数据集上给出了n * log(n):

  

此算法在许多数据集上提供n * log(n)性能,导致其他快捷方式降级为二次性能

答案 4 :(得分:3)

与Quicksort相比,Mergesort的比较次数较少,但移动元素的数量较多。

在Java中,元素比较是昂贵的,但移动元素很便宜。因此,Mergesort在标准Java库中用于通用排序

在C ++中,复制对象可能很昂贵,而比较对象通常相对便宜。因此,quicksort是C ++库中常用的排序例程。

参考:http://www.cs.txstate.edu/~rp44/cs3358_092/Lectures/qsort.ppt

答案 5 :(得分:1)

首先,Arrays.sort不仅仅使用快速排序,它使用多个算法java1.6以后

请参阅以下来自Arrays类的代码

/ **      *将指定的数组按数字升序排序。      *      *

实施说明:排序算法是Dual-Pivot Quicksort      *由Vladimir Yaroslavskiy,Jon Bentley和Joshua Bloch撰写。这个算法      *在许多导致其他数据集的数据集上提供O(n log(n))性能      *快速降级为二次性能,通常是      *比传统(单枢轴)Quicksort实现更快。      *      * @param要排序的数组      * /     public static void sort(int [] a){         DualPivotQuicksort.sort(一);     }

DualPivotQuicksort.sort(a); // This uses 5 algorithms internally depending upon dataset size 
do checkout the source code of Arrays class.

在java 1.6之前我认为它使用三种算法快速排序原始类型,例如int和mergesort用于对象,当快速排序执行它开始堆排序时,请参阅此处了解更多详细信息 http://cafe.elharo.com/programming/java-programming/why-java-util-arrays-uses-two-sorting-algorithms

答案 6 :(得分:0)

Quicksort平均O(n log(n))平均速度最快,因此Sun可能会将其作为一个很好的指标。

答案 7 :(得分:0)

QuickSort是一种常见的排序算法。它的速度相当快,除非要排序的数据已经是相反的顺序。它在太空中也很有效。

答案 8 :(得分:0)

这取决于你想做什么。正常快速排序的问题是,它有时可以是O(n²)。所以通常你可以使用堆排序,但大多数情况下快速排序更快。

然而,Arrays.sort(...)实现使用了“调整过的快速排序,改编自Jon L. Bentley和M. Douglas McIlroy [...]”(根据JavaDoc文档)。该算法具有一些优化的内置,使其能够在O(n * log(n))上工作,其中普通的快速排序将使用O(n²)。

Arrays.sort算法也会一遍又一遍地进行测试,你可以确定它是有效的并且是无错误的(虽然这不能得到保证。)

iuiz

答案 9 :(得分:0)

Arrays.sort()使用多种排序算法,具体取决于数组中的大小和元素。

  • 小数组的插入排序
  • 合并排序主要是排序数组
  • 高度调整和适应性强的双枢轴和放大器其他一切的单枢轴快速排序

所以在实践中我们看到快速排序对于大型基元数组来说非常快,但是当它需要适应部分排序的数组时,当对象之间的比较缓慢,稳定排序等等时会有一些陷阱。

答案 10 :(得分:0)

自从该线程的最后答案以来已经有一段时间了,这里有一些更新...

java研究这些算法时,取决于复杂性及其与数组大小的相关性以及概率,并且取决于度量和基准。

根据JAVA JDK 1.8 DOCS,它在不选择算法的情况下自我说明 根据一些阈值,只能选择一个,但最多四个...

/**
     * If the length of an array to be sorted is less than this
     * constant, Quicksort is used in preference to merge sort.
     */
    private static final int QUICKSORT_THRESHOLD = 286;

    /**
     * If the length of an array to be sorted is less than this
     * constant, insertion sort is used in preference to Quicksort.
     */
    private static final int INSERTION_SORT_THRESHOLD = 47;

    /**
     * If the length of a byte array to be sorted is greater than this
     * constant, counting sort is used in preference to insertion sort.
     */
    private static final int COUNTING_SORT_THRESHOLD_FOR_BYTE = 29;

    /**
     * If the length of a short or char array to be sorted is greater
     * than this constant, counting sort is used in preference to Quicksort.
     */
    private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 3200;

参考 Java DOC JDK 8

该事件演变为使用并行排序 Sorting in Java

Java 8 带有一个新的API – parallelSort –具有与Arrays.sort() API相似的签名:

@Test
public void givenIntArray_whenUsingParallelSort_thenArraySorted() {
    Arrays.parallelSort(toSort);

    assertTrue(Arrays.equals(toSort, sortedInts));
}

parallelSort ()的幕后,它将数组分成不同的子数组(根据parallelSort算法中的粒度)。每个子数组都在不同的线程中用 Arrays.sort ()进行排序,以便可以并行执行排序并最终将其合并为一个排序的数组。

请注意,ForJoin公共池用于执行这些并行任务,然后合并结果。

Arrays.parallelSort的结果将与Array.sort相同,这只是利用多线程的问题。

最后,Arrays.parallelSort中也有API Arrays.sort的类似变体:

Arrays.parallelSort (int [] a, int fromIndex, int toIndex);

摘要: 因此,随着Java API随硬件和软件的发展而发展 多线程和调优在这里和那里有更多用途 在阈值和算法上。

答案 11 :(得分:0)

Arrays.sort()不使用快速排序。 Java 7使用的TimSort是合并排序和插入排序的组合。 当元素数量更多时,Java 8使用并行排序,并使用多个线程进行排序。否则它会使用TimSort。

因此,最坏情况下的时间复杂度始终为O(nlogn)

相关问题