Stefan.Nilsson@hut.fi
namespace mbm_radixsort {
typedef unsigned char* string;
enum { SIZE = 1024, THRESHOLD = 10 };
typedef struct { string *sa; int sn, si; } mbmstack_t;
static void simplesort(string a[], int n, int b)
{
int i, j;
string tmp;
for (i = 1; i < n; i++)
for (j = i; j > 0 && stringtools::scmp(a[j-1]+b, a[j]+b) > 0; j--)
{ tmp = a[j]; a[j] = a[j-1]; a[j-1] = tmp; }
}
static void rsorta(string *a, int n, int b)
{
#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
#define stackempty() (sp <= stack)
mbmstack_t stack[SIZE], *sp = stack, *oldsp, *bigsp;
string *pile[256], *ak, *an, r;
static int count[256], cmin, nc;
int *cp, c, cmax;
push(a, n, b);
while(!stackempty()) {
pop(a, n, b);
if(n < THRESHOLD) {
simplesort(a, n, b);
continue;
}
an = a + n;
if(nc == 0) {
cmin = 255;
for(ak = a; ak < an; ) {
c = (*ak++)[b];
if(++count[c] == 1 && c > 0) {
if(c < cmin) cmin = c;
nc++;
}
}
if(sp+nc > stack+SIZE) {
rsorta(a, n, b);
continue;
}
}
oldsp = bigsp = sp, c = 2;
pile[0] = ak = a+count[cmax=0];
for(cp = count+cmin; nc > 0; cp++, nc--) {
while(*cp == 0) cp++;
if (*cp > 1) {
if(*cp > c) c = *cp, bigsp = sp;
push(ak, *cp, b+1);
}
pile[cmax = cp-count] = ak += *cp;
}
std::swap(*oldsp, *bigsp);
an -= count[cmax];
count[cmax] = 0;
for(ak = a; ak < an; ak += count[c], count[c] = 0) {
r = *ak;
while(--pile[c = r[b]] > ak)
std::swap(*pile[c], r);
*ak = r;
}
}
}
void mbm_radix(string a[], size_t n)
{ rsorta(a, n, 0); }
#undef push
#undef pop
#undef stackempty
CONTESTANT_REGISTER(mbm_radix,
"mbm/radixsort",
"MSD Radix Sort by P. M. McIlroy, K. Bostic, and M. D. McIlroy")
}