【问题标题】:Why does Java's Arrays.sort method use two different sorting algorithms for different types?为什么 Java 的 Arrays.sort 方法对不同的类型使用两种不同的排序算法?
【发布时间】:2011-04-12 01:17:57
【问题描述】:

Java 6 的Arrays.sort 方法对基元数组使用快速排序,对对象数组使用合并排序。我相信大多数时候快速排序比合并排序更快,并且消耗更少的内存。我的实验支持这一点,尽管两种算法都是 O(n log(n))。那么为什么不同的类型使用不同的算法呢?

【问题讨论】:

标签: java algorithm quicksort mergesort


【解决方案1】:

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

由于原始类型没有标识(无法区分具有相同值的两个整数),因此这对它们来说无关紧要。但是对于引用类型,它可能会导致某些应用程序出现问题。因此,对这些使用稳定的归并排序。

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

【讨论】:

  • 使用快速排序的另一个原因是,在平均情况下,快速排序比归并排序更快。尽管快速排序比归并排序做更多的比较,但它做的数组访问却少得多。如果输入包含大量重复条目,3-way quicksort 也可以实现线性时间,这在实际应用中并不罕见(我猜双轴快速排序也有这个属性)。
  • 对于原始类型它不会克隆数组,它可以将它们就地排序,所以我认为唯一的原因是稳定性合同,基本上......
【解决方案2】:

根据 this answer 中引用的 Java 7 API 文档,对象数组的 Arrays#Sort() 现在使用 TimSort,它是 MergeSort 和 InsertionSort 的混合体。另一方面,原始数组的Arrays#sort() 现在使用Dual-Pivot QuickSort。这些更改从 Java SE 7 开始实施。

【讨论】:

  • 这不是一个答案,为什么选择了 2 种不同的算法。
【解决方案3】:

我能想到的一个原因是快速排序的最坏情况时间复杂度为 O(n^2),而合并排序的最坏情况时间复杂度为 O(n log n)。对于对象数组,可以预期会有多个重复的对象引用,这是快速排序最差的一种情况。

有一个不错的visual comparison of various algorithms,要特别注意不同算法的最右边的图表。

【讨论】:

  • Java 快速排序是一种修改后的快速排序,不会降级为 O(n^2),来自文档“此算法在许多数据集上提供 n*log(n) 性能,导致其他快速排序降级为二次性能"
【解决方案4】:

我正在参加 Coursera 的算法课程,并且在 Bob Sedgewick 教授的其中一场讲座中提到了 Java 系统排序的评估:

"如果程序员使用对象,也许空间不是关键 重要的考虑因素和合并排序使用的额外空间可能 不是问题。如果程序员使用原始类型,也许 性能是最重要的,所以他们使用快速排序。”

【讨论】:

  • 这不是主要原因。在那句话之后,有一个问题嵌入到视频中,关于“为什么使用 MergeSort 引用类型?” (因为它很稳定)。我认为 Sedgewick 没有在视频中提到这一点,以留待质疑。
【解决方案5】:

java.util.Arraysquicksort 用于 int 等原始类型,将 mergesort 用于实现 Comparable 的对象> 或使用比较器。使用两种不同方法的想法是,如果程序员使用对象,空间可能不是一个至关重要的考虑因素,因此 mergesort 使用的额外空间可能不是问题,如果程序员使用原始类型,则可能是性能是最重要的,所以请使用 快速排序

例如: 这是排序稳定性很重要的示例。

这就是为什么稳定排序对对象类型有意义,尤其是可变对象类型和具有比排序键更多数据的对象类型,而归并排序就是这样一种排序。但对于原始类型而言,稳定性不仅无关紧要。没有意义。

来源:INFO

【讨论】:

    【解决方案6】:

    Java 的Arrays.sort 方法使用快速排序、插入排序和归并排序。 OpenJDK 代码中甚至同时实现了单轴快速排序和双轴快速排序。最快的排序算法取决于具体情况,获胜者是:小数组的插入排序(目前选择了 47 个),大多数排序数组的归并排序和剩余数组的快速排序,因此 Java 的 Array.sort() 尝试选择最佳算法根据这些标准申请。

    【讨论】:

      猜你喜欢
      • 2011-07-21
      • 1970-01-01
      • 2014-08-02
      • 1970-01-01
      • 2012-12-06
      • 1970-01-01
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多