为什么Java';s Arrays.sort方法对不同类型使用两种不同的排序算法?

为什么Java';s Arrays.sort方法对不同类型使用两种不同的排序算法?,java,algorithm,quicksort,mergesort,Java,Algorithm,Quicksort,Mergesort,Java6的Arrays.sort方法对原语数组使用快速排序,对对象数组使用合并排序。我相信大多数情况下,快速排序比合并排序更快,而且占用内存更少。我的实验支持这一点,尽管两种算法都是O(nlog(n))。那么为什么不同的类型使用不同的算法呢?最可能的原因是:快速排序不稳定,即相同的条目可以在排序过程中改变它们的相对位置;除其他外,这意味着如果对已排序的数组进行排序,它可能不会保持不变 由于基元类型没有标识(无法区分具有相同值的两个int),因此这对它们并不重要。但对于引用类型,它可能会给某些应

Java6的
Arrays.sort
方法对原语数组使用快速排序,对对象数组使用合并排序。我相信大多数情况下,快速排序比合并排序更快,而且占用内存更少。我的实验支持这一点,尽管两种算法都是O(nlog(n))。那么为什么不同的类型使用不同的算法呢?

最可能的原因是:快速排序不稳定,即相同的条目可以在排序过程中改变它们的相对位置;除其他外,这意味着如果对已排序的数组进行排序,它可能不会保持不变

由于基元类型没有标识(无法区分具有相同值的两个int),因此这对它们并不重要。但对于引用类型,它可能会给某些应用程序带来问题。因此,对这些对象使用稳定的合并排序


OTOH,不为基元类型使用(保证n*log(n))稳定合并排序的原因可能是它需要克隆数组。对于引用类型,引用对象通常比引用数组占用更多的内存,这通常无关紧要。但对于基元类型,克隆数组会使内存使用量增加一倍。

我能想到的一个原因是,快速排序的最坏情况时间复杂度为O(n^2),而mergesort的最坏情况时间复杂度为O(n log n)。对于对象数组,有一个公平的期望,即将有多个重复的对象引用,这是quicksort做得最差的一种情况


对于不同的算法,有一个合适的、特别注意最右边的图。

我在上关于算法的课程,在Bob Sedgewick教授的一次讲座中提到了Java系统排序的评估:

“如果程序员正在使用对象,那么空间可能不是关键因素 重要的考虑因素和合并排序可能使用的额外空间 没问题。如果程序员使用的是基元类型,也许 性能是最重要的,因此他们使用快速排序。”


根据中引用的Java 7 API文档,
Arrays#Sort()
现在用于对象数组,它是MergeSort和InsertionSort的混合体。另一方面,原语数组的
数组#sort()
现在使用。这些更改是从JavaSE7开始实现的。

Java的
数组。sort
方法使用快速排序、插入排序和合并排序。OpenJDK代码中甚至实现了单轴和双轴快速排序。最快的排序算法取决于具体情况,胜利者是:针对小数组的插入排序(目前选择了47个)、针对大部分排序的数组的合并排序,以及针对其余数组的快速排序,因此Java的Array.sort()是尝试根据这些标准选择要应用的最佳算法。

java.util.Arrays对基本类型使用快速排序,如int和合并排序用于实现可比或使用比较器的对象。使用两种不同方法的想法是,如果程序员使用对象空间可能不是一个非常重要的考虑因素,那么mergesort使用的额外空间可能不是问题,如果程序员使用原语类型可能性能是最重要的,那么使用快速排序

例如: 这就是排序稳定性问题的例子

这就是为什么稳定排序对对象类型有意义,尤其是可变对象类型和数据量超过排序键的对象类型,而mergesort就是这样一种排序。但对于原始类型来说,稳定性不仅仅是无关紧要的。这毫无意义


来源:

快速排序最坏的情况是N^2而不是NlogN。等等,如果你有一个
整数的数组或什么的,会发生什么?这在你阅读的源代码中没有解释吗?这些信息不再是最新的。从JavaSE7开始,MergeSort被替换为,QuickSort被替换为。有关Java API文档的链接,请参见下面的回答。另请参见,对于JDK 7+请参见,Java quicksort是一种经过修改的快速排序,它不会从文档中降级为O(n^2),“此算法在许多数据集上提供n*log(n)性能,导致其他快速排序降级为二次性能”,这不是主要原因。就在这句话之后,视频中嵌入了一个问题:“为什么引用类型使用MergeSort?”(因为它是稳定的)。我想Sedgewick在视频中没有提到这一点,这让人怀疑。使用快速排序的另一个原因是,在一般情况下,快速排序比合并排序快。尽管quicksort比mergesort做得更多,但它做的数组访问要少得多。如果输入包含大量重复条目,则三向快速排序也可以实现线性时间,这在实际应用中并不少见(我猜dual pivot quick sort也具有此属性)。对于基本类型,它不会克隆数组,它可以对其进行适当排序,因此我认为唯一的原因是稳定性契约,基本上…这不是一个答案,为什么选择了两种不同的算法。