Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/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
Algorithm 为什么会有不同的递归调用快速排序的方法?_Algorithm_Quicksort - Fatal编程技术网

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