20230407 10.1. 快速排序

发布时间 2023-06-21 16:27:27作者: 流星<。)#)))≦

快速排序

快速排序

什么是快速排序算法的最好情况?每次正好中分 T(N) = O( NlogN )

void Quicksort( ElementType A[], int N ) 
{ 
    if ( N < 2 ) return;
    pivot = 从A[]中选一个主元; 
    将S = { A[] \ pivot } 分成2个独立子集:
        A1={ a∈S | a <= pivot } 和
        A2={ a∈S | a >= pivot };
    A[] =   Quicksort(A1,N1) ∪
                    {pivot} ∪
            Quicksort(A2,N2);
}
  • 主元的选择至关重要,有多种取法
    • 取头、中、尾的中位数
      • 例如 8、12、3的中位数就是8

快速排序的问题

  • 用递归……
  • 对小规模的数据(例如N不到100)可能还不如插入排序快
    解决方案
  • 当递归的数据规模充分小,则停止递归,直接调用简单排序(例如插入排序)
  • 在程序中定义一个Cutoff的阈值

算法实现

void Quick_Sort(ElementType A[],int N) 
{ 
    Quicksort( A, 0, N-1 ); 
}


void Quicksort( ElementType A[], int Left, int Right ) 
{ 
    if ( Cutoff <= Right-Left ) {
        Pivot = Median3( A, Left, Right );
        i = Left; j = Right – 1;
        for( ; ; ) { 
            while ( A[ ++i ] < Pivot ) { }
            while ( A[ ––j ] > Pivot ) { }
            if ( i < j ) 
                Swap( &A[i], &A[j] );
            else break;
        } 
        Swap( &A[i], &A[ Right-1 ] );
        Quicksort( A, Left, i-1 ); 
        Quicksort( A, i+1, Right );
    }
    else
        Insertion_Sort( A+Left, Right-Left+1 );
}


ElementType Median3( ElementType A[], int Left, int Right ) 
{ 
    int Center = ( Left + Right ) / 2; 
    if ( A[ Left ] > A[ Center ] ) 
        Swap( &A[ Left ], &A[ Center ] ); 
    if ( A[ Left ] > A[ Right ] ) 
        Swap( &A[ Left ], &A[ Right ] ); 
    if ( A[ Center ] > A[ Right ] ) 
        Swap( &A[ Center ], &A[ Right ] ); 
    /* A[ Left ] <= A[ Center ] <= A[ Right ] */ 
    Swap( &A[ Center ], &A[ Right-1 ] ); /* 将pivot藏到右边 */ 
    /* 只需要考虑 A[ Left+1 ] … A[ Right–2 ] */
    return A[ Right-1 ]; /* 返回 pivot */ 
}