【问题标题】:Java & Merge SortJava & 合并排序
【发布时间】:2011-03-23 19:20:59
【问题描述】:

为什么 Java impl 选择合并排序而不是快速排序?为什么他们将内容复制到数组中?

API:“排序算法是一种修改过的合并排序(如果低位子列表中的最高元素小于高位子列表中的最低元素,则忽略合并)。该算法提供有保证的 n log(n) 性能. 这个实现将指定的列表转储到一个数组中,对数组进行排序,然后迭代列表,从数组中的相应位置重置每个元素。这避免了尝试对链表进行排序导致的 n2 log(n) 性能到位。”

【问题讨论】:

  • @Johannes ...教训是实现细节发生了变化。也可能是其中一个或两个 javadocs 中的材料已过期。
  • @Stephen C:如果记录在案,尤其是在性能保证方面,则不是实现细节。
  • @Thomas 我同意,性能保证不能是实现细节。但是算法可以。
  • @Thomas - 那么你如何与@Johannes 所说的关于集合排序从 Java 6 到 Java 7 的变化相协调呢?他们可以并且确实会更改实现细节……即使它们已记录在 javadocs 中。
  • @NoozNooz42 - Java 平台默认执行并行排序是个坏主意。如果您的平台不是多核野兽怎么办?如果您不想要排序以使用所有可用内核怎么办?如果集合太小而无法并行排序怎么办?如果您希望您的应用程序使用并行排序,只需使用第三方库...

标签: java sorting


【解决方案1】:

Java 开发人员将最坏情况与 avg 情况进行了交换,您可能知道,在最坏情况下,快速排序可能会在 O(n^2) 中运行..

您可以在 API 中阅读,对链表进行就地排序更复杂 n^2log(n)

归并排序是稳定的,但对于高效版本的快速排序来说并非如此。 (这在对对象进行排序时非常重要 + 许多程序员在使用 Collections.sort() 时认为这是理所当然的)

【讨论】:

    【解决方案2】:

    我认为选择归并排序的主要原因是因为它是稳定的。

    其他人提到的 n log n 最坏情况保证是一个优势,但这可能不是主要原因。如果您查看Arrays.sort 方法,所有对原语的排序都使用快速排序,而对Object[] 的排序使用合并排序。这是因为稳定排序对原语无关紧要。相同的基元彼此无法区分。

    【讨论】:

      【解决方案3】:

      文档为您的两个问题提供了答案:

      此算法提供有保证的 n log(n) 性能。

      归并排序没有快速排序的病态

      归并排序相对于快速排序的另一个优势是归并排序是稳定的。快速排序通常是不稳定的。 (显然,通过足够的努力,您可以使其稳定,但我相信这样做的成本相对较高。)

      这避免了 n2 log(n) 性能 这将导致试图 就地对链表进行排序。

      首先复制到数组中意味着您不必依赖原始集合访问单个元素的复杂性。我想它可以查看列表是否实现了RandomAccess,如果是,就进行排序,但RandomAccess 仅在1.4 中引入。

      【讨论】:

        【解决方案4】:
        • 合并排序保证了 O(n log n) 的行为。快速排序的最坏情况性能为 O(n^2)。所以在某些情况下,归并排序更快,而且它有更好的上限。

        • 正如您的引文所述,像快速排序这样的就地排序不适用于链接列表。为了对所有类型的集合进行可预测的工作,需要一份副本。

        • 快速排序本身并不稳定。稳定性有时是可取的,这也是 API 应该提供的。

        【讨论】:

        • bullet #2 是有问题的,因为他们确实将内容复制到了一个数组中,所以他们无论如何都可以对数组进行快速排序......
        猜你喜欢
        • 1970-01-01
        • 2012-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多