快速选择算法
我们可以将快速排序算法稍作修改将其应用在选择问题上,该算法称为快速选择算法,复杂度O(NlogN),最坏情况为O(N^2)。令|A|为A中的元素个数,查找A中第k个最小元,算法步骤如下:
1)如果|A|=1,那么k=1,则将A中的元素作为答案返回
2)取A中一元素V,称为枢纽元。
3)将A-{V}分为两个不相交的集合:A1和A2,其中A1中的元素值小于等于V,A2中的元素值大于等于V
4)若k<=|A1|,那么第k个最小元必然在A1中,在这种情况下返回quciksort(A1,k).如果k=1+|A1|,那么枢纽元就是第K个元素,我们将其返回。否则第k个最小元就在|A2|中,它是A2中的第(k-|A1|-1)个最小元,则递归调用返回quicksort(A2,k-|A1|-1).
#define Cutoff ( 10 )
void
Qselect( ElementType A[ ], int k, int Left, int Right )
{
int i, j;
ElementType Pivot;
/* 1*/ if( Left + Cutoff <= Right )
{
/* 2*/ Pivot = Median3( A, Left, Right );
/* 3*/ i = Left; j = Right - 1;
/* 4*/ for( ; ; )
{
/* 5*/ while( A[ ++i ] < Pivot ){ }
/* 6*/ while( A[ --j ] > Pivot ){ }
/* 7*/ if( i < j )
/* 8*/ Swap( &A[ i ], &A[ j ] );
else
/* 9*/ break;
}
/*10*/ Swap( &A[ i ], &A[ Right - 1 ] ); /* Restore pivot */
/*11*/ if( k <= i )
/*12*/ Qselect( A, k, Left, i - 1 );
/*13*/ else if( k > i + 1 )
/*14*/ Qselect( A, k, i + 1, Right );
}
else /* Do an insertion sort on the subarray */
/*15*/ InsertionSort( A + Left, Right - Left + 1 );
}
该算法结束时,第k小的元素就在数组中第k个位置。