在典型的现代架构中,高效的快速排序实现通常优于归并排序以对RAM-based数组进行排序。[需要引证]另一方面,归并排序是一种稳定的排序方法,更有效地处理难以访问的连续媒体。
我的问题:
如果要排序的数据可以全部放入内存中,为什么快速排序比归并排序表现更好?如果所有需要的数据都被缓存或在内存中,那么访问快速排序和归并排序不都应该很快吗?
为什么归并排序在处理访问缓慢的顺序数据(例如在数据无法全部放入内存的情况下从磁盘中读取)时更有效率?
在由n个元素组成的原始数据(数据是连续的)数组
arr
中。在归并排序中必须读取和比较的元素对是arr[0]
和arr[n/2]
(发生在最后合并)。现在考虑在快速排序中必须读取和比较的元素对是arr[1]
和arr[n]
(发生在第一次分区,假设我们将随机选择的枢轴与第一个元素交换)。我们知道数据是以块的形式读取并加载到缓存或磁盘中(如果我错了,请纠正我),那么使用归并排序时,所需数据在加载到一个块中的可能性就更大了吗?它似乎总是比较更接近的元素,因此归并排序似乎总是更占优势。我知道这是错误的(请参见下面的图表),因为快速排序显然更快......我知道归并排序不是原地排序,需要额外的内存,这可能会减慢速度。除此之外,我的分析中还缺少哪些要素?
这些图片来自于普林斯顿大学计算机科学中的归并排序和快速排序幻灯片。
我的动机:
我想理解上述概念,因为它们是为什么在排序链表或非连续数据时使用归并排序,而在排序数组或连续数据时使用快速排序的主要原因之一。以及为什么在Java中使用归并排序来对对象进行排序,而使用快速排序来对基本类型进行排序。
更新:Java 7 API实际上使用TimSort来对对象进行排序,这是归并排序和插入排序的混合体。对于基本类型,则使用双轴快速排序。这些更改自Java SE 7开始实施。这与排序算法的稳定性有关。 为什么Java的Arrays.sort方法使用两种不同的排序算法处理不同类型的数据?
编辑:
我希望得到一个回答,涉及以下方面:
- 我知道这两种排序算法在移动次数、读取和比较方面有所不同。如果这些原因导致了我在问题列表中看到的行为(我怀疑),那么请详细解释排序算法的步骤和过程是如何导致在从磁盘或内存中获取数据时具有优势或劣势的。
- 欢迎提供示例。我更喜欢通过示例学习。
注意:如果您正在阅读@rcgldr的答案,请查看我们在聊天室中的对话,其中有很多好的解释和细节。https://chat.stackoverflow.com/rooms/161554/discussion-between-rcgldr-and-oliver-koo