为什么Merge sort用于Android / Java API中的对象?

时间:2015-03-02 04:46:34

标签: java android sorting quicksort mergesort

在原始类型的Java Arrays.sort()中使用快速排序。另一方面,对象的Arrays.sort()使用Merge排序。同样适用于Collection.sort(),它也使用Merge排序。集合排序使用下面的Arrays排序实现。所以,简单来说,我可以说基元是使用快速排序排序的,但是对象是使用合并排序进行排序的。

我的猜测是它与自己的排序算法有关。关于快速排序与合并排序的SO有很多讨论,例如thisthis。似乎存在相互冲突的主张哪个更好,这是可以理解的,因为这取决于数据集。

我的理解是

  • 到位:快速排序获胜。合并排序可以在链接列表
  • 的就地实现
  • 外部存储数据:合并排序获胜。
  • 排序列表(由任何形式的链接列表支持):合并排序获胜。 Link

Android API似乎遵循与Java相同的模式。这是我在Arrays.java

中找到的
    public static void sort(long[] array) {
    DualPivotQuicksort.sort(array);
}

而且,

public static void sort(Object[] array) {
    ComparableTimSort.sort(array);
}

我不明白的是,是什么让Merge排序成为在Java或Android中排序对象的好选择?为什么不把这个决定留给开发者?

4 个答案:

答案 0 :(得分:7)

关键问题是排序稳定性 - 如果从排序顺序的角度看两个元素相等,它们是否会以与输入中相同的顺序出现在结果中。

对于例如long。输入中3的所有实例都将组合在一起,没有人关心哪个实例。

另一方面,对象可能以不影响排序顺序的方式不同。如果您按腿数分类动物,您可能会关心“猫”和“狗”是否保持原始顺序。

Arrays.sort mergesort稳定。用于基元的快速排序不需要稳定。

答案 1 :(得分:2)

请参阅此答案:Why Collections.sort uses merge sort instead of quicksort?

TL; DR:

  与mergesort相比,QuickSort有两个主要缺陷:

     
      
  1. 它不稳定(正如parsifal所说)。
  2.   
  3. 它不能保证n log n的性能;它可以降低到病理输入的二次性能。
  4.   

答案 2 :(得分:2)

我认为

的问题
  

是什么使合并排序成为排序Java对象的良好候选者   对原语进行快速排序?

已被其他人回答,但问题是

  

为什么这个决定还没有留给开发人员?

尚未得到解决。

事实上,任何开发人员都可以轻松地从CollectionArrayList 隐藏 sort()方法派生新类(由于sort()static方法,因此必须 hidden, not overidden )并使用自己的自定义实现。

这很少(如果有的话)完成的事实可能是因为今天的大多数年轻程序员比C ++更多地接触Java。在Java社区中,"抽象"这意味着你不知道一个类的底层实现是如何工作的,而且你不需要。 JVM的机器独立性使我们对速度/效率权衡的直觉变得愚蠢。因此,我们中的许多人对数据结构和算法的理解并不像一些较老的,经验丰富的程序员那样清晰。

这几乎与对C ++中抽象的理解相反。引用Alex Stepanov:

  

事实上,我不相信图书馆可以消除   程序员需要了解算法和数据结构。它   只是消除了程序员实现它们的需要。一个需要   了解要使用的数据结构的基本属性   它们适当地使应用程序满足其自身的复杂性   要求。

答案 3 :(得分:1)

合并排序是稳定的:由于排序

,不会重新排序相等的元素