快速排序分析和行为

时间:2016-06-10 10:56:01

标签: algorithm sorting quicksort

我正在阅读关于Algorithms第4版Robert Sedgewick的书中的快速排序算法。

  

Quicksort很受欢迎,因为它实施起来并不困难   适用于各种不同类型的输入数据,并且是   比典型的任何其他排序方法快得多   应用。快速排序算法的理想功能就是它   就地(仅使用一个小的辅助堆栈)并且它需要   时间与N log N成正比,对长度数组进行排序   N.到目前为止,我们所考虑的算法都没有结合这些算法   两个属性。

     

此外,quicksort的内环比其他大部分短   排序算法,这意味着它在实践中也很快   理论上。它的主要缺点是它在某种意义上是脆弱的   在实施过程中需要注意一些必须避免的问题   表现不好。

我对上述文字的疑问是

  1. 作者的意思是“只使用一个小的辅助堆栈”?

  2. 作者的意思是“quicksort的内循环比大多数其他排序算法短”?

  3. 请求用简单的例子来解释。

    由于

4 个答案:

答案 0 :(得分:1)

  

1作者的意思是“仅使用一个小的辅助堆栈”?

除了要排序的数据之外,作者意味着还需要很少的额外内存。因此,排序期间生成的数据结构不会产生很大的开销。

  
      
  1. 作者的意思是“quicksort的内循环比大多数其他排序算法短”?
  2.   

作者意味着在最里面的循环中要执行的指令的数量是完全可见的,这对于例如cpu缓存。

在内部循环的下面的代码中,只有索引递增/递减。因此检查了循环条件。

作为示例,我采用了wikipedia

中提到的实现
algorithm quicksort(A, lo, hi) is
    if lo < hi then
        p := partition(A, lo, hi)
        quicksort(A, lo, p – 1)
        quicksort(A, p + 1, hi)

algorithm partition(A, lo, hi) is
pivot := A[lo]
i := lo – 1
j := hi + 1
loop forever
    do
        i := i + 1
    while A[i] < pivot
    do
        j := j – 1
    while A[j] > pivot
    if i >= j then
        return j
    swap A[i] with A[j]

答案 1 :(得分:1)

  1. 作者的意思是“仅使用一个小的辅助堆栈”?
  2. 您还需要考虑quick-sortin-place排序算法。

    in-place表示:

    • in-place功能大大降低了存储要求。
    • 它使用恒定的存储量(读取:固定数量的额外变量)以便于分类过程。

    因此,由于存储量小且固定,因此表示quick-sort“只使用一个小的辅助堆栈”。

    1. 作者的意思是“quicksort的内循环比大多数其他排序算法短”?
    2. 这可能意味着内部循环内部的逻辑很简单,因此需要的代码更少。这个“较短的内循环”不应与循环迭代的次数混淆。因为在任何级别的递归树上,迭代的总数仅为“n”。

答案 2 :(得分:1)

  

1作者的意思是“仅使用一个小的辅助堆栈”?

在理想情况下,quicksort在堆栈上使用O(log2(n))空间,在最坏的情况下,它使用堆栈上的O(n)空间,占用的空间比排序的数组多。

  
      
  1. 作者的意思是“quicksort的内循环比大多数其他排序算法短”?
  2.   

这在现代系统上可能无关紧要,因为任何合理大小的内部循环都适合大多数处理器的代码缓存。条件分支将影响管道性能,具体取决于分支预测。

  快速排序......比典型应用中的任何其他排序方法快得多。

事实并非如此,在最好的情况下,快速排序仅比合并排序稍微快一些(小于10%),而在最坏的情况下,快速排序则慢得多(O(n ^ 2)与O(n log) (N))。合并排序的主要问题是它需要一个与原始数组相同大小或1/2大小的临时数组。

答案 3 :(得分:0)

function QuickSort(Array, Left, Right)
var
  L2, R2, PivotValue
begin
 Stack.Push(Left, Right);       // pushes Left, and then Right, on to a stack
 while not Stack.Empty do
 begin
     Stack.Pop(Left, Right);    // pops 2 values, storing them in Right and then Left
     repeat
         PivotValue := Array[(Left + Right) div 2];
         L2 := Left;
         R2 := Right;
         repeat
             while Array[L2] < PivotValue do // scan left partition
                 L2 := L2 + 1;
             while Array[R2] > PivotValue do // scan right partition
                 R2 := R2 - 1;
             if L2 <= R2 then
             begin
                 if L2 != R2 then
                     Swap(Array[L2], Array[R2]);  // swaps the data at L2 and R2
                 L2 := L2 + 1;
                 R2 := R2 - 1;
             end;
         until L2 >= R2;
         if R2 - Left > Right - L2 then // is left side piece larger?
         begin
             if Left < R2 then
                 Stack.Push(Left, R2);
             Left := L2;
         end;
         else
         begin
             if L2 < Right then // if left side isn't, right side is larger
                 Stack.Push(L2, Right);
             Right := R2;
         end;
     until Left >= Right;
 end;
 end;
  
      
  1. 作者的意思是“仅使用一个小的辅助堆栈”?
  2.   

你不需要第二个数组来存储(比如mergesort)它是在同一个内存中计算的

  

作者的意思是“quicksort的内循环比大多数短   其他排序算法“?

快速排序的非常快的部分是内部循环(//扫描左侧分区和//扫描右侧分区) 因为它只是增加和检查......而不是更多。