|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 1986 (0x7c2)
Types: TextFile
Notes: UNIX file
Names: »qsort.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »libc/gen/qsort.c«
/*
* Quicker sort algorithm (from C. A. R. Hoare)
* This uses linear insertion sort for number of elements
* smaller than M in some partitioning.
*/
char *qmedian();
#define M 10
qsort(base, nel, width, compar)
register char *base;
unsigned nel, width;
int (*compar)();
{
register char *bot, *top;
bot = base;
top = base + nel*width;
if (nel < M) {
if (nel > 1)
qlinsert(bot, nel, width, compar);
return;
}
qexchange(bot, qmedian(compar, bot, bot+(nel/2)*width, top-width), width);
for (;;) {
while ((*compar)(base, bot+=width)>=0 && bot<top)
;
while ((*compar)(top-=width, base)>=0 && top>base)
;
if (bot < top)
qexchange(bot, top, width);
else
break;
}
qexchange(top, base, width);
qsort(base, (top-base)/width, width, compar);
qsort(bot, nel - (bot-base)/width, width, compar);
}
/*
* Exchange two records pointed to by
* `p1' and `p2'. Each record is of `width'
* bytes.
*/
static
qexchange(p1, p2, width)
register char *p1, *p2;
register unsigned width;
{
int save;
if (width)
do {
save = *p1;
*p1++ = *p2;
*p2++ = save;
} while (--width);
}
/*
* Produce the median of the first, middle,
* and last elements of a file by calling
* the compare routine.
*/
static char *
qmedian(comp, a, b, c)
int (*comp)();
char *a, *b, *c;
{
register char *bmin, *bmax;
if ((*comp)(a, b) < 0) {
bmin = a;
bmax = b;
} else {
bmin = b;
bmax = a;
}
if ((*comp)(bmax, c) < 0)
return (bmax);
return ((*comp)(bmin, c) < 0 ? c : bmin);
}
/*
* Linear insertion sort used to speed up
* final sorts when parititions get relatively small.
*/
static
qlinsert(base, nel, width, compar)
char *base;
register unsigned nel;
unsigned width;
int (*compar)();
{
register char *min, *mbase;
int n;
--nel;
do {
n = nel;
min = base;
mbase = min+width;
do {
if ((*compar)(mbase, min) < 0)
min = mbase;
mbase += width;
} while (--n);
qexchange(min, base, width);
base += width;
} while (--nel);
}