Algorithm 为什么会有不同的递归调用快速排序的方法?
我注意到递归调用快速排序的方式存在差异 一种方法是Algorithm 为什么会有不同的递归调用快速排序的方法?,algorithm,quicksort,Algorithm,Quicksort,我注意到递归调用快速排序的方式存在差异 一种方法是 quicksort(Array, left, right) x = partition(Array, left, right) quicksort(Array, left, x-1) quicksort(Array, x+1, right) partition(array, left, right) pivotIndex := choose-pivot(array, left, right) pivot
quicksort(Array, left, right)
x = partition(Array, left, right)
quicksort(Array, left, x-1)
quicksort(Array, x+1, right)
partition(array, left, right)
pivotIndex := choose-pivot(array, left, right)
pivotValue := array[pivotIndex]
swap array[pivotIndex] and array[right]
storeIndex := left
for i from left to right - 1
if array[i] ≤ pivotValue
swap array[i] and array[storeIndex]
storeIndex := storeIndex + 1
swap array[storeIndex] and array[right] // Move pivot to its final place
return storeIndex
这是有意义的,因为快速排序的工作原理是围绕枢轴对其他元素进行分区,因此元素数组[x]应该位于其最终位置。因此,范围[left,partition-1]和[partition+1,right]保持不变
另一种方式
quicksort(Array, left, right)
x = partition(Array, left, right)
quicksort(Array, left, x)
quicksort(Array, x+1, right)
PARTITION(A,p,r)
x A[p]
i p - 1
j r + 1
while TRUE
do repeat j j - 1
until A[j] x
repeat i i + 1
until A[i] x
if i < j
then exchange A[i] A[j]
else return j
快速排序(数组、左、右)
x=分区(数组、左、右)
快速排序(数组,左,x)
快速排序(数组,x+1,右)
分区(A、p、r)
xa[p]
i p-1
j r+1
虽然是真的
重复j-1
直到A[j]x
重复i+1
直到A[i]x
如果我
请注意,缺少-1。这似乎表明数组已正确分区,但没有单个元素处于其最终位置。如果我在第二种方式中加入-1,输入数组的排序不正确,那么这两种方式是不能互换的
是什么导致了这种差异?很明显,这是分区方法中的某个地方,它是否与使用霍尔或卢穆托的算法有关?如果你仔细想想,另一种方法不会对算法产生任何影响。如果分区算法与第一个分区算法相同,则在其中一个子数组中包含枢轴不会产生任何影响,因为在这种情况下,其他元素都不会与子数组中的枢轴交换位置
最多它会增加一些比较的数量。尽管我不确定这是否会对大型阵列的排序时间产生不利影响。除了在最小阵列上运行外,这两个版本的效率实际上没有太大差异。大部分工作是将一个大小为n的大数组(其值可以在离其正确位置最多n个空间处)分离为两个较小的数组,即使在最坏的情况下,两个较小的数组的值也不能远离其正确位置。“单向”基本上在每一步创建三个分区,但由于第三个分区只占一个空间大,因此它对算法的进展只起到O(1)的作用
也就是说,实现最后的切换非常容易,所以我不确定为什么“另一种方式”示例的代码不采取这一步骤。他们甚至指出了一个陷阱(如果为枢轴选择了最后一个而不是第一个元素,那么递归永远不会结束),通过实现在末尾消除枢轴元素的开关,可以完全避免这个陷阱。我能想象的唯一一种情况是,如果没有其他因素,那么代码空间将处于绝对优势。,排除或传递分区索引可能是关闭间隔和半打开间隔之间的差异:右键可能是第一个不接触的索引-无法从没有引用的不完整代码段中分辨出来。造成这种差异的原因是
partition()
的返回值表示不同的含义
- 在
中,One-way
的返回值是在partition()
之后的partition()
是在Array[x]
partition()中使用的轴
- 在
,另一种方式中
的返回值不是用于该分区的轴所在的位置,即partition()
在数组[x]
是一个小于分区()之后
中使用的轴的元素,但除此之外我们不知道更多。实际枢轴可以位于阵列上半部分的任何位置partition()
另一种方式使用x-1
而不是x
的第一次递归调用很容易给出错误的结果,例如pivot=8
,Array[x]=5
和Array[x-1]=7