快速排序和归并排序有什么区别?

5

我说的对吗?这两种算法都是将你的结构递归地分成两部分,然后按正确顺序构建结构,是这样吗?

那么,它们有什么区别呢?

编辑:我找到了实现快速排序中分区的以下算法,但我真的不明白它是如何工作的,特别是使用 (hi + low) >>> 1 作为参数的交换行!有人能理解这个吗?

private static int partition( int[] items, int lo, int hi ) 
{
    int destination = lo;
    swop( items, (hi + lo) >>> 1, hi );
    // The pivot is now stored in items[ hi ].
    for (int index = lo; index != hi; index ++) 
    {
        if (items[ hi ] >= items[ index ]) 
        {
            // Move current item to start.
            swop( items, destination, index );
            destination ++;
        }

        // items[ i ] <= items[ hi ] if lo <= i < destination.
        // items[ i ] > items[ hi ] if destination <= i <= index.
    }

    // items[ i ] <= items[ hi ] if lo <= i < destination.
    // items[ i ] > items[ hi ] if destination <= i < hi.
    swop( items, destination, hi );
    // items[ i ] <= items[ destination ] if lo <= i <= destination.
    // items[ i ] > items[ destination ] if destination < i <= hi.
    return destination;
}
6个回答

22

我说的对吗,这两种算法都只是把你的结构递归地分成两个部分,然后按正确的顺序构建你的结构吗?

是的。然而,它们的区别在于何时以正确的顺序构建结构。在快速排序中,实际的排序步骤是在分割过程中完成的(将元素移动到左半边或右半边,这要根据与主元素比较的结果而定),并且没有合并步骤来返回到树的上一级(从数据角度观察;当然,您的实现可能需要堆栈展开);而在归并排序中,排序是在向上的过程中完成的——分割步骤根本不移动任何元素,但在返回上一层时,你需要合并两个排序好的列表。

至于性能比较:快速排序的最坏情况确实比归并排序更糟糕,但平均情况下的常数因子(几乎总是在实践中观察到)较小,这使得快速排序通常是通用、未排序输入的优胜者。并不是很多人需要自己实现通用排序程序...


9
在最坏情况下,快速排序的时间复杂度为O(n^2),而归并排序的时间复杂度为O(n*log n)。
快速排序使用一个基准点来将数组分成两部分,并以该基准点为参考点排序这两部分,但存在基准点可能是已排序数组的最大值或最小值的风险。如果选择了错误的基准点,则时间复杂度将达到n^2(n^2次比较)。
归并排序是根据名称递归地将数组分成相同大小的两半,并将它们合并回去。例如,在wikipedia上有非常好的解释。特别是带有树状拆分图的图片似乎很好地解释了它。

4
快速排序最坏情况下的效率较差,而归并排序始终保证是O(n log n),但实际上典型的快速排序实现比归并排序更快。此外,归并排序需要额外的存储空间,在许多情况下(例如库例程)这是一个问题。这就是为什么库例程几乎总是使用快速排序的原因。
编辑:我找到了以下实现快速排序中分区的算法,但我不太理解它的工作原理,特别是使用(hi + low) >>> 1作为参数的交换行!
这将hi和low的平均值取出,相当于(hi + low) / 2。

2
底层数据结构的实现细节也是一个因素,例如快速排序所需的高效随机访问和数据结构的可变性将影响内存需求(特别是归并排序)。

0

是的,快速排序和归并排序都是分治算法

维基百科的快速排序页面有一个简短的比较:

快速排序算法还与归并排序竞争,归并排序也是一种递归排序算法,但具有最坏情况 O(n log n) 的运行时间优势。归并排序是一种稳定排序算法,不像快速排序和堆排序,可以很容易地适应链表和存储在慢速访问媒体(如磁盘存储或网络附加存储)上的非常大的列表。虽然快速排序可以被写成在链表上操作,但它经常受到无法随机访问的坏的枢轴选择的影响。归并排序的主要缺点是,在数组上操作时,它在最佳情况下需要 O(n) 的辅助空间,而使用原地划分和尾递归的快速排序变体仅使用 O(log n) 的空间。(请注意,在链表上操作时,归并排序仅需要一个小的、恒定量的辅助存储器。)

-1

http://zh.wikipedia.org/wiki/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95 在那里,您可以快速了解常见的排序算法。 快排和归并排序是前两种 ;)

如Jan所说,更多信息请阅读有关每个算法的信息。 归并排序始终具有O(n * log n)的复杂度,而快速排序在最坏情况下可达到O(n ^ 2)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接