我正在阅读关于quicksort的内容,看看不同的实现,我正试图绕过一些东西。
在this实现中(当然有效),将枢轴选为中间元素,然后左右指针相应地向右和向左移动,交换元素到枢轴周围的分区。
我正在尝试数组[4,3,2,6,8,1,0]。
在第一个分区上,pivot为6,所有左侧元素都已小于6,因此左指针将停在枢轴上。在右侧,我们将交换0与6,然后是1和8,因此在第一次迭代结束时,数组将如下所示:
[4,3,2,0,1,8,6]。
然而,我的印象是,在快速排序中的每次迭代之后,枢轴最终会在正确的位置,因此它应该最终位于阵列的第5位。
所以,有可能(并且确定)枢轴没有在正确的迭代中结束,或者是否是我遗漏的明显事物?
答案 0 :(得分:4)
快速排序算法有许多可能的变体。在这一个中,枢轴在迭代中不在正确的位置是可以的。
快速排序算法的每个变体的定义特征是在分区步骤之后,我们在数组的开头有一个部分,其中所有元素都小于或等于pivot,并且在所有元素大于或等于pivot的数组的结尾。它们之间可能还有一个部分,每个元素都等于枢轴。这种布局确保在我们对左侧部分和右侧部分进行递归调用后,并保持中间部分不变时,整个数组将被排序。
注意,通常等于pivot的元素可以转到数组的任何部分。快速排序的一个很好的实现,避免了最明显的情况下的二次时间,即所有相等的元素,必须合理地扩展元素之间等于枢轴的元素。
可能的变体包括:
因此,快速排序的正确和有效实现非常棘手(还存在选择良好的枢轴的问题,对于该问题,存在多种具有不同权衡的方法;或者优化切换到另一种非递归排序算法对于较小的子阵列尺寸)。
此外,您链接的实现似乎可以对重叠的子数组进行递归调用:
if (i <= j) {
exchange(i, j);
i++;
j--;
}
例如,当i
等于j
时,这些元素将被交换,i
将变为大于j
2。之后,3个元素将以下递归调用的范围之间重叠。但代码似乎仍能正常工作。