为什么Java impl选择合并排序而不是快速排序?为什么他们将内容复制到数组?
API:“排序算法是一个经过修改的mergesort(如果低子列表中的最高元素小于高子列表中的最低元素,则省略合并。)此算法提供有保证的n log(n)性能这个实现将指定的列表转储到一个数组中,对数组进行排序,并遍历列表,从数组中的相应位置重置每个元素。这样可以避免尝试排序链表时产生的n2 log(n)性能到位。“
答案 0 :(得分:8)
Java家伙用平均情况交易了最坏情况,你可能知道,在最坏的情况下,快速排序可能会在O(n ^ 2)中运行..
你可以在API中读取,就地排序链表更复杂n ^ 2log(n)
合并排序是稳定的,对于快速排序的高效版本而言并非如此。 (这对于排序对象非常重要+许多程序员在使用Collections.sort()时认为这是理所当然的)
答案 1 :(得分:6)
文档给出了两个问题的答案:
此算法可提供有保证的n log(n)性能。
合并排序没有快速排序的病态案例
合并排序比quicksort的另一个优点是合并排序稳定;快速排序通常不稳定。 (显然,如果付出足够的努力,你可以使稳定,但我认为这样做相对昂贵。)
这避免了n 2 log(n)性能 这会导致尝试 对链接列表进行排序。
首先复制到数组意味着您不依赖于原始集合访问单个元素的复杂性。我认为可以查看列表是否实现RandomAccess
并进行排序,但是RandomAccess
仅在1.4中引入。
答案 2 :(得分:4)
我认为选择mergesort的主要原因是因为它稳定。
其他人提到的n log n最坏情况保证是一个优势,但可能不是主要原因。如果查看Arrays.sort
方法,基元上的所有排序都使用快速排序,Object[]
上的排序使用mergesort。这是因为稳定排序对于原语无关紧要;相等的原语是不可分辨的。
答案 3 :(得分:0)
合并排序保证了O(n log n)行为。快速排序的最差情况是O(n ^ 2)。所以在某些情况下,合并排序更快,并且它有更好的上限。
正如您的引用所提到的,快速排序等就地排序不适用于链接列表。要以可预测的方式为所有类型的集合工作,需要一份副本。
快速排序本身并不稳定。有时候需要稳定性,以及API应该提供的东西。