快速选择算法
我们可以将快速排序算法稍作修改将其应用在选择问题上,该算法称为快速选择算法,复杂度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个位置。