Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 为什么合并排序更适合大型阵列,而快速排序更适合小型阵列?_Arrays_Sorting_Data Structures_Quicksort_Mergesort - Fatal编程技术网

Arrays 为什么合并排序更适合大型阵列,而快速排序更适合小型阵列?

Arrays 为什么合并排序更适合大型阵列,而快速排序更适合小型阵列?,arrays,sorting,data-structures,quicksort,mergesort,Arrays,Sorting,Data Structures,Quicksort,Mergesort,我认为使用合并排序而不是快速排序的唯一原因是列表是否已经(或大部分)排序 合并排序需要更多的空间,因为它创建了一个额外的数组用于存储,无论它将比较每个项目 另一方面,快速排序不需要额外的空间,也不需要交换或比较过多的空间 如果说由于数据集的大小,一个数据集比另一个数据集好,这似乎是不直观的 例如,引用Geeksforgek的文章: 合并排序可以很好地处理任何类型的数据集,而不管其大小(大或小)。 鉴于 快速排序不能很好地处理大型数据集 接下来它说: 合并排序不到位,因为它需要额外的内存空间来存储

我认为使用合并排序而不是快速排序的唯一原因是列表是否已经(或大部分)排序

合并排序需要更多的空间,因为它创建了一个额外的数组用于存储,无论它将比较每个项目

另一方面,快速排序不需要额外的空间,也不需要交换或比较过多的空间

如果说由于数据集的大小,一个数据集比另一个数据集好,这似乎是不直观的

例如,引用Geeksforgek的文章:

合并排序可以很好地处理任何类型的数据集,而不管其大小(大或小)。 鉴于 快速排序不能很好地处理大型数据集

接下来它说:

合并排序不到位,因为它需要额外的内存空间来存储辅助数组。 鉴于 快速分拣已经就位,因为它不需要任何额外的存储

我知道空间复杂性和时间复杂性是分开的。但这仍然是一个额外的步骤,当然,在一个新的数组中使用大数据集写入所有内容需要更多的时间


至于数据透视问题,数据集越大,选择最低或最高项的可能性越低(除非它是一个几乎排序的列表)

那么,为什么认为合并排序比快速排序更适合对大型数据集进行排序呢

为什么合并排序更适合大型阵列,而快速排序更适合小型阵列? 如果说由于数据集的大小,一个数据集比另一个数据集好,这似乎是不直观的

假设数据集适合内存(而不是分页),问题不是数据集的大小,而是导致O(n2)时间复杂性的特定快速排序实现的最坏情况模式。快速排序可以使用中间值来保证最坏情况下的时间复杂度为O(nlog(n)),但这最终使它比合并排序慢得多。另一种方法是,如果递归级别变得太深(称为intro-sort),并在某些库中使用,则切换到堆排序

合并排序需要更多的空间,因为它创建了一个额外的数组用于存储,无论它将比较每个项目

合并排序的一些变体不需要任何额外的数据存储,但它们往往比标准合并排序慢50%左右

另一方面,快速排序不需要额外的空间,也不需要交换或比较过多的空间

子数组的每个元素都将与pivot元素进行比较。随着相等元素数的增加,Lomuto划分方案变差,而Hoare划分方案变好。由于有很多相等的元素,霍尔分区方案不需要交换相等的元素,但是避免交换的检查通常比交换花费更多的时间

对指向对象的指针数组进行排序

合并排序比快速排序执行更多的移动,但比较次数更少。如果对指向对象的指针数组进行排序,则只移动指针,但比较对象需要指针的不同以及比较对象所需的内容。在这种情况下以及其他比较比移动需要更多时间的情况下,合并排序速度更快

内存中不适合的大型数据集

对于太大而无法装入内存的数据集,使用内存基排序对数据集的“块”进行排序,这些数据集将装入内存,然后写入外部存储器。然后,使用k-way合并来合并外部存储上的“块”,以生成排序数据集

除了rcgldr的详细回复外,我还想强调一些额外的注意事项:

  • 大数组和小数组是相对的:在许多库中,小数组(少于30到60个元素)通常使用插入排序进行排序。该算法更简单,如果数组已经排序,则是最优的,尽管在最坏的情况下具有二次复杂度

  • 除了空间和时间的复杂性之外,稳定性是一个可能需要的特性,在某些情况下甚至是必要的。合并排序和插入排序都是稳定的(比较相等的元素保持相同的相对顺序),而使用快速排序很难实现稳定性

  • 正如您所提到的,快速排序的最坏情况时间复杂度为O(N2),并且库不实现中间值来抑制这种下降趋势。许多只使用中位数3或中位数9,有些在两个分支上天真地递归,为最坏情况下的堆栈溢出铺平了道路。这是一个主要问题,因为数据集可能被精心设计,以显示最坏情况的行为,从而导致拒绝服务攻击、服务器速度减慢甚至崩溃。道格·麦克罗伊(Doug McIlroy)在其1999年的著名论文中发现了这个问题。使用此技术(cf)实施的实现和攻击都是错误的

  • 几乎排序的数组在实践中非常常见,无论是快速排序还是合并排序都不能真正有效地处理它们。库现在使用更高级的技术组合,例如,以实现更好的性能和稳定性


“数据集越大,选择最低或最高项目的可能性越低(除非它是一个几乎排序的列表)。”好的,但除了最低、最高或中间的项目外,还有其他元素可以选择。考虑一下,如果在一个递归调用中处理1/4的元素,在另一个递归调用中处理3/4的元素,性能会发生什么变化。现在想想快速排序和合并排序是如何分割列表的。快速排序可以很容易地将列表平均或接近平均地一分为二吗?你能分类吗?为什么?快速排序可以使用中间值来保证最坏情况下的时间复杂度为O(n log(n)),恐怕这不是真的。中间带的中间带仅确保从较大的一半雕刻至少3个元素。精心制作的数据集仍然存在