快速排序到已排序的数组

问题描述

此问题:https://www.quora.com/What-is-randomized-quicksort

Alejo Hausner告诉:在最坏的情况下,快速排序的成本

具有讽刺意味的是,如果将quicksort应用于已排序的数组,则可能会得到这种代价高昂的行为

我不明白。有人可以向我解释。

https://www.quora.com/What-will-be-the-complexity-of-quick-sort-if-array-is-already-sorted可能是对此的答案,但这并没有给我完整的答复。

解决方法

根据实现方式,有几种“通用”方式来选择枢轴。

通常,对于“未分类”来源,没有选择它的好坏方法。 因此,某些实现只是将第一个元素作为枢轴。

对于已经分类的源,这会导致最坏的数据透视,因为这样的间隔永远都是空的。 ->递归步骤= O(n)而不是所需的O(log n)。
这会导致O(n²)复杂性,这对于排序非常不利。


随机选择枢轴可避免这种情况。如上所述,在每次递归中随机选择的枢轴极不可能具有相同的不良特性。

由于您无法预测随机生成器的选择(如果是好的),因此不可能故意生成不良源

,

Quicksort算法是这样的:

  • 选择一个枢轴
  • 将小于枢轴的元素移动到起点,将大于枢轴的元素移动到终点
  • 现在数组看起来像[<=p,<=p,p,>p,>p]
  • 对数组的第一和第二“一半”进行递归排序

如果数据透视图始终总是靠近数组中间,那么Quicksort将非常有效,运行时间接近n log n。如果枢轴是中间值,则此方法非常有效。但是,选择实际的中位数本身将是昂贵的。如果由于不幸而发生支点变化,成为数组中的最小或最大元素,您将得到一个像这样的数组:[p,>p]。如果这种情况经常发生,则您的“快速排序”实际上就像选择排序一样。在那种情况下,由于要递归排序的子数组的大小在每次迭代时仅减少1,因此将有n个迭代级别,每个级别都要花费n个运算,因此总体复杂度为`n ^ 2。

现在,由于我们不愿意使用昂贵的操作来找到一个好的支点,因此我们不妨随机选择一个元素。而且由于我们也不在乎真正的随机性,所以我们可以从数组中选择任意元素,例如第一个。

如果随机地对数组进行随机混洗,那么选择第一个元素就很棒。您可以合理地希望它将定期为您提供“平均”元素。但是如果数组已经被排序了……那么根据定义,第一个元素是最小的。因此,在复杂度为n^2的糟糕情况下。

避免“不良列表”的一种简单方法是选择一个真正的随机元素,而不是一个任意元素。或者,如果您有理由相信通常会在几乎已排序的列表上调用快速排序,则可以选择位置n/2的元素,而不是位置1的元素。

也有几篇关于选择枢轴的不同方法的研究论文,其中包括对复杂性影响的精确计算。例如,您可以选择三个随机元素,将它们从最小到最大排列,并保持中间一个。但是得出的结论通常是:如果您尝试编写更好的枢轴选择,那么这样做也会更加昂贵,并且算法的整体复杂性不会得到太大改善。