Quicksort:一个分区后的枢轴位置

时间:2015-01-21 13:56:43

标签: algorithm sorting quicksort

我正在阅读关于quicksort的内容,看看不同的实现,我正试图绕过一些东西。

this实现中(当然有效),将枢轴选为中间元素,然后左右指针相应地向右和向左移动,交换元素到枢轴周围的分区。

我正在尝试数组[4,3,2,6,8,1,0]。

在第一个分区上,pivot为6,所有左侧元素都已小于6,因此左指针将停在枢轴上。在右侧,我们将交换0与6,然后是1和8,因此在第一次迭代结束时,数组将如下所示:

[4,3,2,0,1,8,6]。

然而,我的印象是,在快速排序中的每次迭代之后,枢轴最终会在正确的位置,因此它应该最终位于阵列的第5位。

所以,有可能(并且确定)枢轴没有在正确的迭代中结束,或者是否是我遗漏的明显事物?

1 个答案:

答案 0 :(得分:4)

快速排序算法有许多可能的变体。在这一个中,枢轴在迭代中不在正确的位置是可以的。

快速排序算法的每个变体的定义特征是在分区步骤之后,我们在数组的开头有一个部分,其中所有元素都小于或等于pivot,并且在所有元素大于或等于pivot的数组的结尾。它们之间可能还有一个部分,每个元素都等于枢轴。这种布局确保在我们对左侧部分和右侧部分进行递归调用后,并保持中间部分不变时,整个数组将被排序。

注意,通常等于pivot的元素可以转到数组的任何部分。快速排序的一个很好的实现,避免了最明显的情况下的二次时间,即所有相等的元素,必须合理地扩展元素之间等于枢轴的元素。

可能的变体包括:

  • 中间部分仅包含1个元素:枢轴。在这种情况下,pivot在分区之后在数组中占据最终位置,并且不会在递归调用中使用。这就是您在其迭代中占据一席之地的意思。对于这种方法,良好的实现必须移动大约一半的元素等于枢轴到左边部分而另一半移动到右边部分,否则我们将有一个二次时间用于具有所有相等元素的数组。
  • 没有中间部分。枢轴和与其相等的所有元素分布在左右两部分之间。这就是您链接的实现所做的事情。再次,在这种方法中,大约一半的元素等于枢轴应该到左边部分,另一半到右边部分。这也可以与第一个变体混合,这取决于我们是否使用奇数或偶数元素对数组进行排序。
  • 每个等于pivot的元素都会转到中间部分。左侧或右侧部分没有与枢轴相等的元素。这非常有效,而Wikipedia示例用于解决所有元素相等的问题。在这种情况下,所有元素彼此相等的数组按线性时间排序。

因此,快速排序的正确和有效实现非常棘手(还存在选择良好的枢轴的问题,对于该问题,存在多种具有不同权衡的方法;或者优化切换到另一种非递归排序算法对于较小的子阵列尺寸)。

此外,您链接的实现似乎可以对重叠的子数组进行递归调用:

if (i <= j) {
  exchange(i, j);
  i++;
  j--;
}

例如,当i等于j时,这些元素将被交换,i将变为大于j 2。之后,3个元素将以下递归调用的范围之间重叠。但代码似乎仍能正常工作。