You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

293 lines
5.6 KiB
C++

#pragma once
namespace NSet
{
template <class T>
class AFX_EXT_CLASS CQuickSort
{
public:
CQuickSort(void) {};
/*!> is quicker than sort_array for arrays larger than about 100 values. */
static void quickSort( T* arr, int sz );
//参数二是参数一的原始索引号
static void quickSort( T* arr, int* iarr, int sz );
protected:
static void partSort( T* arr, int istart, int istop, int* jstart, int* jstop );
static void sortFor( T* arr, int sz, int itarget );
static void insertionSort( T* arr, int istart, int istop );
static void partSort( T* arr, int* iarr, int istart, int istop, int* jstart, int* jstop);
static void insertionSort( T* arr, int* iarr, int istart, int istop );
static void sortFor( T* arr, int* iarr, int sz, int itarget );
};
//////////////////////////////////////////////////////////////////////////////
//实现代码
#define NSMALL 7
#define FM 7875
#define FA 211
#define FC 1663
#define NSTACK 50
template <class T>
void CQuickSort<T>::partSort( T* arr, int istart, int istop, int* jstart, int* jstop )
{
int ipivot, ileft, iright;
T pivotval, tmp;
static long int seed = 0L;
seed = (seed * FA + FC) % FM;
ipivot = (int)(istart + (istop-istart) * (float)seed / (float)FM + .5);
if ( ipivot < istart ) ipivot = istart;
if ( ipivot > istop ) ipivot = istop;
pivotval = arr[ipivot];
for ( ileft=istart, iright=istop; ; )
{
while ( arr[ileft] <=pivotval && ileft<istop ) ileft++;
while ( arr[iright]>=pivotval && iright>istart ) iright--;
if ( ileft < iright )
{
tmp = arr[ileft];
arr[ileft++] = arr[iright];
arr[iright--] = tmp;
}
else break;
}
if ( ileft < ipivot )
{
tmp = arr[ileft];
arr[ileft++] = arr[ipivot];
arr[ipivot] = tmp;
}
else if ( ipivot < iright )
{
tmp = arr[iright];
arr[iright--] = arr[ipivot];
arr[ipivot] = tmp;
}
*jstart = iright;
*jstop = ileft;
}
template <class T>
void CQuickSort<T>::insertionSort( T* arr, int istart, int istop )
{
int i, j;
T arr_i;
for ( i=istart+1; i<=istop; i++ )
{
for ( arr_i=arr[i],j=i; j>istart && arr[j-1]>arr_i; j-- )
arr[j] = arr[j-1];
arr[j] = arr_i;
}
}
template <class T>
void CQuickSort<T>::sortFor( T* arr, int sz, int itarget )
/*!> sorts the array until the 'itarget' element has exactly the right
value. The rest of the array must be considered unsorted after the operation,
although it will generally be better sorted. */
{
int j, k, p = 0, q = sz-1;
while( q - p > NSMALL )
{
partSort( arr, p, q, &j, &k );
if ( itarget <= j ) q = j;
else if ( itarget >= k ) p = k;
else return;
}
insertionSort( arr, p, q );
}
template <class T>
void CQuickSort<T>::quickSort( T* arr, int sz )
/*!> is quicker than sort_array for arrays larger than about 100 values. */
{
int pstack[NSTACK], qstack[NSTACK], j, k, p, q, top=0;
pstack[top] = 0;
qstack[top++] = sz - 1;
while( top )
{
p = pstack[--top];
q = qstack[top];
while( q - p > NSMALL )
{
partSort( arr, p, q, &j, &k );
if ( j-p < q-k )
{
pstack[top] = k;
qstack[top++] = q;
q = j;
}
else
{
pstack[top] = p;
qstack[top++] = j;
p = k;
}
}
insertionSort( arr, p, q );
}
}
template <class T>
void CQuickSort<T>::quickSort( T* arr, int* iarr, int sz )
{
int pstack[NSTACK], qstack[NSTACK], j, k, p, q, top=0;
pstack[top] = 0;
qstack[top++] = sz - 1;
while( top )
{
p = pstack[--top];
q = qstack[top];
while( q - p > NSMALL )
{
partSort( arr, iarr, p, q, &j, &k );
if ( j-p < q-k )
{
pstack[top] = k;
qstack[top++] = q;
q = j;
}
else
{
pstack[top] = p;
qstack[top++] = j;
p = k;
}
}
insertionSort( arr, iarr, p, q );
}
}
template <class T>
void CQuickSort<T>::partSort( T* arr, int* iarr, int istart, int istop, int* jstart, int* jstop)
{
int ipivot, ileft, iright;
T pivotval, tmp;
int itmp;
static long int seed = 0L;
seed = (seed * FA + FC) % FM;
ipivot = (int)(istart + (istop-istart) * (float)seed / (float)FM);
if ( ipivot < istart ) ipivot = istart;
if ( ipivot > istop ) ipivot = istop;
pivotval = arr[ipivot];
for ( ileft=istart, iright=istop; ; )
{
while ( arr[ileft] <=pivotval && ileft<istop ) ileft++;
while ( arr[iright]>=pivotval && iright>istart ) iright--;
if ( ileft < iright )
{
itmp = iarr[ileft];
tmp = arr[ileft];
iarr[ileft] = iarr[iright];
arr[ileft++] = arr[iright];
iarr[iright] = itmp;
arr[iright--] = tmp;
}
else break;
}
if ( ileft < ipivot )
{
itmp = iarr[ileft];
tmp = arr[ileft];
iarr[ileft] = iarr[ipivot];
arr[ileft++] = arr[ipivot];
iarr[ipivot] = itmp;
arr[ipivot] = tmp;
}
else if ( ipivot < iright )
{
itmp = iarr[iright];
tmp = arr[iright];
iarr[iright] = iarr[ipivot];
arr[iright--] = arr[ipivot];
iarr[ipivot] = itmp;
arr[ipivot] = tmp;
}
*jstart = iright;
*jstop = ileft;
}
template <class T>
void CQuickSort<T>::insertionSort( T* arr, int* iarr, int istart, int istop )
{
int i, j;
T arr_i;
int iarr_i;
for ( i=istart+1; i<=istop; i++ )
{
for ( iarr_i=iarr[i],arr_i=arr[i],j=i; j>istart && arr[j-1]>arr_i; j-- )
{
arr[j] = arr[j-1];
iarr[j] = iarr[j-1];
}
arr[j] = arr_i;
iarr[j] = iarr_i;
}
}
template <class T>
void CQuickSort<T>::sortFor( T* arr, int* iarr, int sz, int itarget )
{
int j, k, p = 0, q = sz-1;
while( q - p > NSMALL )
{
partSort( arr, iarr, p, q, &j, &k );
if ( itarget <= j ) q = j;
else if ( itarget >= k ) p = k;
else return;
}
insertionSort( arr, iarr, p, q );
}
#undef NSMALL
#undef FM
#undef FA
#undef FC
#undef NSTACK
}//namesapce NSet
using namespace NSet;