我在一次面试中被问到这个问题。它们都是O(nlogn),但大多数人使用快速排序而不是归并排序。为什么呢?


当前回答

为什么快速排序很好?

QuickSort takes N^2 in worst case and NlogN average case. The worst case occurs when data is sorted. This can be mitigated by random shuffle before sorting is started. QuickSort doesn't takes extra memory that is taken by merge sort. If the dataset is large and there are identical items, complexity of Quicksort reduces by using 3 way partition. More the no of identical items better the sort. If all items are identical, it sorts in linear time. [This is default implementation in most libraries]

快速排序总是比归并排序好吗?

不是真的。

归并排序是稳定的,但快速排序不是。所以如果你需要输出的稳定性,你可以使用归并排序。在许多实际应用中需要稳定性。 现在内存很便宜。因此,如果Mergesort使用的额外内存对您的应用程序不是至关重要的,那么使用Mergesort也没有什么害处。

注意:在java中,Arrays.sort()函数对基本数据类型使用快速排序,对对象数据类型使用归并排序。因为对象消耗内存开销,所以为归并排序增加一点开销对于性能来说可能不是什么问题。

参考:在Coursera上观看普林斯顿算法课程第三周的快速排序视频

其他回答

亩! 快速排序并不比归并排序更好,它非常适合于不同类型的应用。

归并排序是值得考虑的,如果速度是本质,糟糕的最差情况性能不能容忍,并且有额外的空间可用

你说他们«他们都是O(nlogn)[…]»。这是错误的。«快速排序使用大约n^2/2比较在最坏的情况下。

然而,根据我的经验,最重要的属性是在使用带有命令式范式的编程语言进行排序时,可以轻松实现顺序访问。

1 Sedgewick,算法

与归并排序不同,快速排序不使用辅助空间。而归并排序使用辅助空间O(n)。 归并排序的最坏情况时间复杂度是O(nlogn)而快速排序的最坏情况复杂度是O(n²)这发生在数组已经排序的时候。

维基百科上关于快速排序的词条:

Quicksort also competes with mergesort, another recursive sort algorithm but with the benefit of worst-case Θ(nlogn) running time. Mergesort is a stable sort, unlike quicksort and heapsort, and can be easily adapted to operate on linked lists and very large lists stored on slow-to-access media such as disk storage or network attached storage. Although quicksort can be written to operate on linked lists, it will often suffer from poor pivot choices without random access. The main disadvantage of mergesort is that, when operating on arrays, it requires Θ(n) auxiliary space in the best case, whereas the variant of quicksort with in-place partitioning and tail recursion uses only Θ(logn) space. (Note that when operating on linked lists, mergesort only requires a small, constant amount of auxiliary storage.)

实际上,快速排序是O(n2)。它的平均情况运行时间是O(nlog(n)),但最坏情况是O(n2),这发生在在包含很少唯一项的列表上运行时。随机化花费O(n)。当然,这并没有改变最坏的情况,它只是防止恶意用户使您的排序花费很长时间。

快速排序更受欢迎,因为它:

(MergeSort需要额外的内存,与要排序的元素数量成线性关系)。 有一个小的隐藏常数。

快速排序是一种就地排序算法,因此它更适合于数组。另一方面,归并排序需要额外的O(N)存储空间,更适合于链表。

与数组不同,在喜欢列表中,我们可以在中间插入O(1)空间和O(1)时间的项,因此归并排序中的归并操作可以在不需要任何额外空间的情况下实现。但是,为数组分配和取消分配额外空间会对归并排序的运行时间产生不利影响。归并排序也有利于链表,因为数据是按顺序访问的,没有太多的随机内存访问。

另一方面,快速排序需要大量的随机内存访问,而使用数组,我们可以直接访问内存,而不需要像链表那样进行任何遍历。同样,快速排序用于数组时具有良好的引用局部性,因为数组连续存储在内存中。

尽管这两种排序算法的平均复杂度都是O(NlogN),但通常人们在执行普通任务时使用数组进行存储,因此快速排序应该是首选算法。

编辑:我刚刚发现归并排序最差/最好/平均情况总是nlogn,但快速排序可以从n2(最坏的情况下,元素已经排序)到nlogn(平均/最佳情况下,pivot总是将数组分为两半)。