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


当前回答

这是采访中经常被问到的一个问题,尽管归并排序在最坏情况下性能更好,但快速排序被认为比归并排序更好,特别是对于大输入。以下是快速排序更好的原因:

1-辅助空间:快速排序是一种就地排序算法。就地排序意味着执行排序不需要额外的存储空间。另一方面,归并排序需要一个临时数组来归并已排序的数组,因此它并不到位。

2-最坏情况:快速排序O(n^2)的最坏情况可以通过使用随机化快速排序来避免。通过选择正确的枢轴,可以很容易地避免这种情况。通过选择合适的枢轴元来获得平均情况下的行为,从而提高了算法的性能,达到了与归并排序一样的效率。

3-引用的局部性:快速排序特别展示了良好的缓存局部性,这使得它在许多情况下比归并排序更快,比如在虚拟内存环境中。

4-尾递归:快速排序是尾递归,而归并排序不是。尾递归函数是一种函数,其中递归调用是函数执行的最后一件事。尾递归函数被认为比非尾递归函数更好,因为尾递归可以被编译器优化。

其他回答

One of the reason is more philosophical. Quicksort is Top->Down philosophy. With n elements to sort, there are n! possibilities. With 2 partitions of m & n-m which are mutually exclusive, the number of possibilities go down in several orders of magnitude. m! * (n-m)! is smaller by several orders than n! alone. imagine 5! vs 3! *2!. 5! has 10 times more possibilities than 2 partitions of 2 & 3 each . and extrapolate to 1 million factorial vs 900K!*100K! vs. So instead of worrying about establishing any order within a range or a partition,just establish order at a broader level in partitions and reduce the possibilities within a partition. Any order established earlier within a range will be disturbed later if the partitions themselves are not mutually exclusive.

任何自下而上的排序方法,如归并排序或堆排序,就像工人或雇员的方法一样,人们很早就开始在微观层面进行比较。但是,一旦在它们之间发现了一个元素,这个顺序就必然会丢失。这些方法非常稳定和可预测,但要做一定量的额外工作。

Quick Sort is like Managerial approach where one is not initially concerned about any order , only about meeting a broad criterion with No regard for order. Then the partitions are narrowed until you get a sorted set. The real challenge in Quicksort is in finding a partition or criterion in the dark when you know nothing about the elements to sort. That is why we either need to spend some effort to find a median value or pick 1 at random or some arbitrary "Managerial" approach . To find a perfect median can take significant amount of effort and leads to a stupid bottom up approach again. So Quicksort says just a pick a random pivot and hope that it will be somewhere in the middle or do some work to find median of 3 , 5 or something more to find a better median but do not plan to be perfect & don't waste any time in initially ordering. That seems to do well if you are lucky or sometimes degrades to n^2 when you don't get a median but just take a chance. Any way data is random. right. So I agree more with the top ->down logical approach of quicksort & it turns out that the chance it takes about pivot selection & comparisons that it saves earlier seems to work better more times than any meticulous & thorough stable bottom ->up approach like merge sort. But

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

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

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

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

1 Sedgewick,算法

在c/c++领域,当不使用stl容器时,我倾向于使用快速排序,因为它是构建的 进入运行时,而归并排序没有。

所以我相信,在许多情况下,这只是阻力最小的途径。

此外,对于整个数据集不适合工作集的情况,快速排序的性能可以高得多。

当我试验这两种排序算法时,通过计算递归调用的次数, 快速排序始终比归并排序具有更少的递归调用。 这是因为快速排序有枢轴,而在下一个递归调用中不包括枢轴。这样快速排序可以比归并排序更快地达到递归基本情况。

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

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

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

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

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